]> git.sesse.net Git - stockfish/commitdiff
Fix gRPC crashes.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 4 Dec 2021 14:47:57 +0000 (15:47 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 4 Dec 2021 14:47:57 +0000 (15:47 +0100)
Since the hash move may change from other threads while we're looking at it,
we could end up applying illegal moves when recovering the PV, corrupting the
state and causing out-of-bounds accesses.

Spotted by vondele.

src/main.cpp

index d24891d9e659f7aab9cdd7ecf16390597b54abc9..359a0d22c2a5016ee135c34d2d24afd510b8cf83 100644 (file)
@@ -157,9 +157,10 @@ void HashProbeImpl::ProbeMove(Position* pos, std::deque<StateInfo>* setup_states
        TTEntry *entry = TT.probe(pos->key(), found);
        response->set_found(found);
        if (found) {
-               Value value = entry->value();
-               Value eval = entry->eval();
-               Bound bound = entry->bound();
+               TTEntry entry_copy = *entry;
+               Value value = entry_copy.value();
+               Value eval = entry_copy.eval();
+               Bound bound = entry_copy.bound();
 
                if (invert) {
                        value = -value;
@@ -171,9 +172,9 @@ void HashProbeImpl::ProbeMove(Position* pos, std::deque<StateInfo>* setup_states
                        }
                }
 
-               response->set_depth(entry->depth());
+               response->set_depth(entry_copy.depth());
                FillValue(eval, response->mutable_eval());
-               if (entry->depth() > DEPTH_NONE) {
+               if (entry_copy.depth() > DEPTH_NONE) {
                        FillValue(value, response->mutable_value());
                }
                response->set_bound(HashProbeLine::ValueBound(bound));
@@ -181,16 +182,20 @@ void HashProbeImpl::ProbeMove(Position* pos, std::deque<StateInfo>* setup_states
                // Follow the PV until we hit an illegal move.
                std::stack<Move> pv;
                std::set<Key> seen;
-               while (found && is_ok(entry->move()) &&
-                      pos->pseudo_legal(entry->move()) &&
-                      pos->legal(entry->move())) {
-                       FillMove(pos, entry->move(), response->add_pv());
+               while (is_ok(entry_copy.move()) &&
+                      pos->pseudo_legal(entry_copy.move()) &&
+                      pos->legal(entry_copy.move())) {
+                       FillMove(pos, entry_copy.move(), response->add_pv());
                        if (seen.count(pos->key())) break;
-                       pv.push(entry->move());
+                       pv.push(entry_copy.move());
                        seen.insert(pos->key());
                        setup_states->push_back(StateInfo());
-                       pos->do_move(entry->move(), setup_states->back());
+                       pos->do_move(entry_copy.move(), setup_states->back());
                        entry = TT.probe(pos->key(), found);
+                       if (!found) {
+                               break;
+                       }
+                       entry_copy = *entry;
                }
 
                // Unroll the PV back again, so the Position object remains unchanged.