mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-07 14:18:18 +02:00
validation: fix UB in LoadChainTip
The removal of the chain tip from setBlockIndexCandidates was happening after nSequenceId was modified. Since the set uses nSequenceId as a sort key, modifying it while the element is in the set is undefined behavior, which can cause the erase to fail. With assumeutxo, a second form of UB exists: two chainstates each have their own candidate set, but share the same CBlockIndex objects. Calling LoadChainTip on one chainstate mutates nSequenceIds that are also in the other chainstate's set. Fix by populating setBlockIndexCandidates after all changes to nSequenceId.
This commit is contained in:
@@ -126,6 +126,13 @@ static ChainstateLoadResult CompleteChainstateInitialization(
|
||||
}
|
||||
}
|
||||
|
||||
// Populate setBlockIndexCandidates in a separate loop, after all LoadChainTip()
|
||||
// calls have finished modifying nSequenceId. Because nSequenceId is used in the
|
||||
// set's comparator, changing it while blocks are in the set would be UB.
|
||||
for (const auto& chainstate : chainman.m_chainstates) {
|
||||
chainstate->PopulateBlockIndexCandidates();
|
||||
}
|
||||
|
||||
const auto& chainstates{chainman.m_chainstates};
|
||||
if (std::any_of(chainstates.begin(), chainstates.end(),
|
||||
[](const auto& cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return cs->NeedsRedownload(); })) {
|
||||
|
||||
Reference in New Issue
Block a user