From: Steinar H. Gunderson Date: Sat, 4 Dec 2021 14:47:57 +0000 (+0100) Subject: Fix gRPC crashes. X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=327916cbecab1b99d17204d8c15b474c17e57c27 Fix gRPC crashes. 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. --- diff --git a/src/main.cpp b/src/main.cpp index d24891d9..359a0d22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -157,9 +157,10 @@ void HashProbeImpl::ProbeMove(Position* pos, std::deque* 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* 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* setup_states // Follow the PV until we hit an illegal move. std::stack pv; std::set 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.