tx_pool: fix use-after-free in prune() - txid was a reference to an item which was later deleted in remove_tx_from_transient_lists(), and txid was used after that
What changed, and why it matters
This commit fixes a use-after-free bug in Monero's transaction pool (tx_pool). The code was storing a reference to a transaction ID, then deleting the underlying data structure that held that ID, and later still using the now-stale reference. The fix simply copies the ID value instead of holding a reference, so it remains valid after deletion. This is a memory-safety bug that could cause crashes or, in the worst case, be exploited to manipulate transaction processing, though the commit itself does not describe any exploit.
Apply the patch. It is a one-line, low-risk change that copies a 32-byte hash by value. After applying, run transaction-pool pruning tests and fuzz/stress-test mempool eviction paths to confirm stability. No additional mitigation is described as necessary.
Security signals we found
use-after-free
dangling reference to container element
transaction pool memory corruption
potential crash or undefined behavior in core daemon
Evidence from the diff
In tx_pool::prune(), the loop iterates over a container and obtains txid as const crypto::hash &txid = it->get_right();. The referenced value belongs to an item that is later removed via remove_tx_from_transient_lists(), invalidating the reference. Subsequent uses of txid (e.g., m_blockchain.get_txpool_tx_meta(txid, meta) and likely further logic) then access freed memory. The patch changes the declaration to const crypto::hash txid = it->get_right();, making a value copy and eliminating the dangling reference.
Changed components
src/cryptonote_core/tx_pool.cpptx_pool::prune()transaction pool / mempool logicInspect captured patch +1 / −1
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 5d729e5..a95a828 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -419,7 +419,7 @@ namespace cryptonote
break;
try
{
- const crypto::hash &txid = it->get_right();
+ const crypto::hash txid = it->get_right();
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
{
Why this scored 59/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.