Guard against UB in lsb/msb
authorlucasart <lucas.braesch@gmail.com>
Tue, 29 Mar 2016 12:37:42 +0000 (20:37 +0800)
committerJoona Kiiski <joona@zoox.com>
Thu, 31 Mar 2016 12:22:37 +0000 (13:22 +0100)
lsb(b) and msb(b) are undefined when b == 0. This can lead to subtle bugs, where
the resulting code behaves differently on different configurations:
- It can be the home grown software LSB/MSB
- It can be the compiler generated software LSB/MSB (when using compiler
  intrinsics without the right compiler flags to allow compiler to use hardware
  LSB/MSB). Which of course depends on the compiler.
- It can be hardware LSB/MSB generated by the compiler.
- Not to mention that hardware LSB/MSB can return different value on different
  hardware when b == 0.

No functional change

Resolves #610

src/bitboard.cpp
src/bitboard.h

index 4ea69eb..ba1af2f 100644 (file)
@@ -81,11 +81,13 @@ namespace {
 /// Software fall-back of lsb() and msb() for CPU lacking hardware support
 
 Square lsb(Bitboard b) {
+  assert(b);
   return BSFTable[bsf_index(b)];
 }
 
 Square msb(Bitboard b) {
 
+  assert(b);
   unsigned b32;
   int result = 0;
 
index 2ad8773..77a824b 100644 (file)
@@ -261,18 +261,27 @@ inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
 
 #if defined(__GNUC__)
 
-inline Square lsb(Bitboard b) { return Square(__builtin_ctzll(b)); }
-inline Square msb(Bitboard b) { return Square(63 - __builtin_clzll(b)); }
+inline Square lsb(Bitboard b) {
+  assert(b);
+  return Square(__builtin_ctzll(b));
+}
+
+inline Square msb(Bitboard b) {
+  assert(b);
+  return Square(63 - __builtin_clzll(b));
+}
 
 #elif defined(_WIN64) && defined(_MSC_VER)
 
 inline Square lsb(Bitboard b) {
+  assert(b);
   unsigned long idx;
   _BitScanForward64(&idx, b);
   return (Square) idx;
 }
 
 inline Square msb(Bitboard b) {
+  assert(b);
   unsigned long idx;
   _BitScanReverse64(&idx, b);
   return (Square) idx;