1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

fix unaligned memory access (UB) on Clang/GCC/MSVC

sample UBSAN report:
client/gui/CAnimation.cpp:329:24: runtime error: load of misaligned address 0x62d0004b094f for type 'const ui32' (aka 'const unsigned int'), which requires 4 byte alignment
This commit is contained in:
Andrey Filipenkov 2022-12-29 13:06:34 +03:00 committed by Ivan Savenko
parent b02948d073
commit db98575d10
2 changed files with 18 additions and 9 deletions

View File

@ -33,6 +33,7 @@ class CDefFile
{
private:
PACKED_STRUCT_BEGIN
struct SSpriteDef
{
ui32 size;
@ -43,7 +44,7 @@ private:
ui32 height;
si32 leftMargin;
si32 topMargin;
} PACKED_STRUCT;
} PACKED_STRUCT_END;
//offset[group][frame] - offset of frame data in file
std::map<size_t, std::vector <size_t> > offset;

View File

@ -20,11 +20,18 @@ VCMI_LIB_NAMESPACE_BEGIN
* memory. On big endian machines, the value will be byteswapped.
*/
#if (defined(linux) || defined(__linux) || defined(__linux__)) && (defined(sparc) || defined(__arm__))
/* SPARC does not support unaligned memory access. Let gcc know when
* to emit the right code. */
struct unaligned_Uint16 { ui16 val __attribute__(( packed )); };
struct unaligned_Uint32 { ui32 val __attribute__(( packed )); };
#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
#if defined(_MSC_VER)
#define PACKED_STRUCT_BEGIN __pragma( pack(push, 1) )
#define PACKED_STRUCT_END __pragma( pack(pop) )
#else
#define PACKED_STRUCT_BEGIN
#define PACKED_STRUCT_END __attribute__(( packed ))
#endif
PACKED_STRUCT_BEGIN struct unaligned_Uint16 { ui16 val; } PACKED_STRUCT_END;
PACKED_STRUCT_BEGIN struct unaligned_Uint32 { ui32 val; } PACKED_STRUCT_END;
static inline ui16 read_unaligned_u16(const void *p)
{
@ -41,14 +48,15 @@ static inline ui32 read_unaligned_u32(const void *p)
#define read_le_u16(p) (SDL_SwapLE16(read_unaligned_u16(p)))
#define read_le_u32(p) (SDL_SwapLE32(read_unaligned_u32(p)))
#define PACKED_STRUCT __attribute__(( packed ))
#else
#warning UB: unaligned memory access
#define read_le_u16(p) (SDL_SwapLE16(* reinterpret_cast<const ui16 *>(p)))
#define read_le_u32(p) (SDL_SwapLE32(* reinterpret_cast<const ui32 *>(p)))
#define PACKED_STRUCT
#define PACKED_STRUCT_BEGIN
#define PACKED_STRUCT_END
#endif