mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-08 22:57:56 +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:
@@ -76,8 +76,13 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager, TestChain100Setup)
|
||||
LOCK(::cs_main);
|
||||
c2.InitCoinsCache(1 << 23);
|
||||
c2.CoinsTip().SetBestBlock(active_tip->GetBlockHash());
|
||||
c2.setBlockIndexCandidates.insert(manager.m_blockman.LookupBlockIndex(active_tip->GetBlockHash()));
|
||||
for (const auto& cs : manager.m_chainstates) {
|
||||
cs->ClearBlockIndexCandidates();
|
||||
}
|
||||
c2.LoadChainTip();
|
||||
for (const auto& cs : manager.m_chainstates) {
|
||||
cs->PopulateBlockIndexCandidates();
|
||||
}
|
||||
}
|
||||
BlockValidationState _;
|
||||
BOOST_CHECK(c2.ActivateBestChain(_, nullptr));
|
||||
@@ -492,6 +497,9 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
|
||||
BOOST_CHECK(cs->setBlockIndexCandidates.empty());
|
||||
}
|
||||
chainman.LoadBlockIndex();
|
||||
for (const auto& cs : chainman.m_chainstates) {
|
||||
cs->PopulateBlockIndexCandidates();
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure that without any assumed-valid BlockIndex entries, only the current tip is
|
||||
|
||||
Reference in New Issue
Block a user