From 327916cbecab1b99d17204d8c15b474c17e57c27 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 4 Dec 2021 15:47:57 +0100 Subject: [PATCH] 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. --- src/main.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) 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. -- 2.39.2