Преглед изворни кода

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
Andrey Filipenkov пре 2 година
родитељ
комит
db98575d10
2 измењених фајлова са 18 додато и 9 уклоњено
  1. 2 1
      client/gui/CAnimation.cpp
  2. 16 8
      lib/vcmi_endian.h

+ 2 - 1
client/gui/CAnimation.cpp

@@ -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;
 

+ 16 - 8
lib/vcmi_endian.h

@@ -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