Fix a crash introduced few days ago
authorMarco Costalba <mcostalba@gmail.com>
Fri, 26 Apr 2013 10:12:53 +0000 (12:12 +0200)
committerMarco Costalba <mcostalba@gmail.com>
Fri, 26 Apr 2013 10:14:01 +0000 (12:14 +0200)
Crash is due to uninitialized ss->futilityMoveCount that
when happens to be negative, yields to an out of range
access in futility_margin().

Bug is subtle because it shows itself only in SMP case.
Indeed in single thread mode we only use the

Stack ss[MAX_PLY_PLUS_2];

Allocated at the begin of id_loop() and due to pure
(bad) luck, it happens that for all the MAX_PLY_PLUS_2
elements, ss[i].futilityMoveCount >= 0

Note that the patch does not prevent futilityMoveCount
to be overwritten after, for instance singular search
or null verification, but to keep things readable and
because the effect is almost unmeasurable, we here
prefer a slightly incorrect but simpler patch.

bench: 4311634

src/search.cpp

index 438c2d6fe858d85e1c72f1ed37c0ec73b74f48ce..cf640a0a90beb33e497474ea514b899d2f006b3b 100644 (file)
@@ -523,6 +523,7 @@ namespace {
     bestValue = -VALUE_INFINITE;
     ss->currentMove = threatMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
     ss->ply = (ss-1)->ply + 1;
+    ss->futilityMoveCount = 0;
     (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO;
     (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
 
@@ -806,7 +807,6 @@ split_point_start: // At split points actual search starts from here
                         << " currmovenumber " << moveCount + PVIdx << sync_endl;
       }
 
-      ss->futilityMoveCount = 0;
       ext = DEPTH_ZERO;
       captureOrPromotion = pos.is_capture_or_promotion(move);
       givesCheck = pos.move_gives_check(move, ci);
@@ -906,6 +906,8 @@ split_point_start: // At split points actual search starts from here
           // far in the move list we are to be more aggressive in the child node.
           ss->futilityMoveCount = moveCount;
       }
+      else
+          ss->futilityMoveCount = 0;
 
       // Check for legality only before to do the move
       if (!RootNode && !SpNode && !pos.pl_move_is_legal(move, ci.pinned))