1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Fix operator[] for vector2d and vector3d being potentially UB (#15977)

We don't have a C++ expert on hand, but taking a pointer to one member
and expecting to access another by an offset is very fishy:
- for one, there could theoretically be padding
- the compiler might assume that we are only writing to that first member

The new code has shown to be free for constant parameter values.
Non-constant ones cause the assembly to have branches (why?), but we don't
use that much.
This commit is contained in:
sfan5 2025-04-08 22:25:45 +02:00 committed by GitHub
parent 46db688cc8
commit a00b9cab36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 39 additions and 30 deletions

View file

@ -85,6 +85,22 @@ typedef char fschar_t;
/** prefer to use the override keyword for new code */ /** prefer to use the override keyword for new code */
#define _IRR_OVERRIDE_ override #define _IRR_OVERRIDE_ override
// Invokes undefined behavior for unreachable code optimization
// Note: an assert(false) is included first to catch this in debug builds
#if defined(__cpp_lib_unreachable)
#include <utility>
#define IRR_CODE_UNREACHABLE() do { _IRR_DEBUG_BREAK_IF(1) std::unreachable(); } while(0)
#elif defined(__has_builtin)
#if __has_builtin(__builtin_unreachable)
#define IRR_CODE_UNREACHABLE() do { _IRR_DEBUG_BREAK_IF(1) __builtin_unreachable(); } while(0)
#endif
#elif defined(_MSC_VER)
#define IRR_CODE_UNREACHABLE() do { _IRR_DEBUG_BREAK_IF(1) __assume(false); } while(0)
#endif
#ifndef IRR_CODE_UNREACHABLE
#define IRR_CODE_UNREACHABLE() (void)0
#endif
//! creates four CC codes used in Irrlicht for simple ids //! creates four CC codes used in Irrlicht for simple ids
/** some compilers can create those by directly writing the /** some compilers can create those by directly writing the
code like 'code', but some generate warnings so we use this macro here */ code like 'code', but some generate warnings so we use this macro here */

View file

@ -131,16 +131,20 @@ public:
T &operator[](u32 index) T &operator[](u32 index)
{ {
_IRR_DEBUG_BREAK_IF(index > 1) // access violation switch (index) {
case 0: return X;
return *(&X + index); case 1: return Y;
default: IRR_CODE_UNREACHABLE();
}
} }
const T &operator[](u32 index) const const T &operator[](u32 index) const
{ {
_IRR_DEBUG_BREAK_IF(index > 1) // access violation switch (index) {
case 0: return X;
return *(&X + index); case 1: return Y;
default: IRR_CODE_UNREACHABLE();
}
} }
//! sort in order X, Y. //! sort in order X, Y.

View file

@ -117,16 +117,22 @@ public:
T &operator[](u32 index) T &operator[](u32 index)
{ {
_IRR_DEBUG_BREAK_IF(index > 2) // access violation switch (index) {
case 0: return X;
return *(&X + index); case 1: return Y;
case 2: return Z;
default: IRR_CODE_UNREACHABLE();
}
} }
const T &operator[](u32 index) const const T &operator[](u32 index) const
{ {
_IRR_DEBUG_BREAK_IF(index > 2) // access violation switch (index) {
case 0: return X;
return *(&X + index); case 1: return Y;
case 2: return Z;
default: IRR_CODE_UNREACHABLE();
}
} }
//! sort in order X, Y, Z. //! sort in order X, Y, Z.

View file

@ -104,8 +104,7 @@ static const VertexType &getVertexTypeDescription(E_VERTEX_TYPE type)
case EVT_TANGENTS: case EVT_TANGENTS:
return vtTangents; return vtTangents;
default: default:
assert(false); IRR_CODE_UNREACHABLE();
CODE_UNREACHABLE();
} }
} }

View file

@ -10,22 +10,6 @@
#include "ILogger.h" #include "ILogger.h"
#include "ITimer.h" #include "ITimer.h"
// CODE_UNREACHABLE(): Invokes undefined behavior for unreachable code optimization
#if defined(__cpp_lib_unreachable)
#include <utility>
#define CODE_UNREACHABLE() std::unreachable()
#elif defined(__has_builtin)
#if __has_builtin(__builtin_unreachable)
#define CODE_UNREACHABLE() __builtin_unreachable()
#endif
#elif defined(_MSC_VER)
#define CODE_UNREACHABLE() __assume(false)
#endif
#ifndef CODE_UNREACHABLE
#define CODE_UNREACHABLE() (void)0
#endif
namespace irr namespace irr
{ {