]> git.sesse.net Git - stockfish/commitdiff
Fix undefined behaviour with unaligned loads in syzygy code
authorJoost VandeVondele <Joost.VandeVondele@gmail.com>
Sat, 5 Nov 2016 08:04:51 +0000 (09:04 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sun, 6 Nov 2016 10:48:07 +0000 (11:48 +0100)
Casting a pointer to a different type with stricter alignment
requirements yields to implementation dependent behaviour.
Practicaly everything is fine for common platforms because the
CPU/OS/compiler will generate correct code, but anyhow it is
better to be safe than sorry.

Testing with dbg_hit_on() shows that the unalignment accesses are
very rare (below 0.1%) so it makes sense to split the code in a
fast path for the common case and a slower path as a fallback.

No functional change (verified with TB enabled).

src/syzygy/tbprobe.cpp

index a1e73c815de9a5eaa0dc27c3f1d7dd85d5b4a132..9debcc6f9393409494ea91af9a768b6fbea2ea0d 100644 (file)
@@ -239,7 +239,13 @@ template<typename T, int LE> T number(void* addr)
     const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
     const bool IsLittleEndian = (Le.c[0] == 4);
 
     const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
     const bool IsLittleEndian = (Le.c[0] == 4);
 
-    T v = *((T*)addr);
+    T v;
+
+    if ((uintptr_t)addr & (alignof(T) - 1)) // Unaligned pointer (very rare)
+        std::memcpy(&v, addr, sizeof(T));
+    else
+        v = *((T*)addr);
+
     if (LE != IsLittleEndian)
         swap_byte(v);
     return v;
     if (LE != IsLittleEndian)
         swap_byte(v);
     return v;