Fix `ChainstateManager::AddChainstate()` assertion crash
What changed, and why it matters
This is a one-line fix in Bitcoin Core that prevents a program crash (assertion failure) when adding a new chainstate. The crash could occur if the previous chainstate did not have a memory pool (mempool) initialized. The change simply checks whether the mempool exists before checking its size, avoiding an invalid memory access. It is a defensive hardening fix rather than a user-triggerable exploit path under normal operation.
Treat as a low-severity hardening fix. Review whether any call path allows an unprivileged user or network message to reach AddChainstate() without a mempool; if not, no urgent action beyond merging is warranted. Include in release notes as a stability fix.
Security signals we found
Null pointer dereference / assertion crash in validation code
Defensive null check added before pointer dereference
Crash in chainstate management during initialization/IBD
No evidence of remote triggerability in the diff
Evidence from the diff
In ChainstateManager::AddChainstate(), the code previously asserted prev_chainstate.m_mempool->size() == 0 unconditionally. If prev_chainstate.m_mempool was nullptr, this would dereference a null pointer and crash. The patch changes the assertion to !prev_chainstate.m_mempool || prev_chainstate.m_mempool->size() == 0, tolerating a missing mempool. This is consistent with the subsequent std::swap and the existing assert(!curr_chainstate.m_mempool). The scenario appears limited to initialization/IBD paths where a chainstate may not yet have a mempool.
Changed components
src/validation.cppChainstateManager::AddChainstate()mempool handling during chainstate creationInspect captured patch +1 / −1
diff --git a/src/validation.cpp b/src/validation.cpp
index 04f60e7b..277c4d3b 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -6248,7 +6248,7 @@ Chainstate& ChainstateManager::AddChainstate(std::unique_ptr<Chainstate> chainst
// Transfer possession of the mempool to the chainstate.
// Mempool is empty at this point because we're still in IBD.
- assert(prev_chainstate.m_mempool->size() == 0);
+ assert(!prev_chainstate.m_mempool || prev_chainstate.m_mempool->size() == 0);
assert(!curr_chainstate.m_mempool);
std::swap(curr_chainstate.m_mempool, prev_chainstate.m_mempool);
return curr_chainstate;
Why this scored 31/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.