SideChain: fixed use-after-free in precalc code

pull/277/head
SChernykh 2023-09-06 10:05:55 +02:00
parent f149613d54
commit 2453c08194
1 changed files with 10 additions and 6 deletions

View File

@ -2061,21 +2061,20 @@ void SideChain::prune_old_blocks()
const uint64_t h = tip->m_sidechainHeight - prune_distance; const uint64_t h = tip->m_sidechainHeight - prune_distance;
uint64_t num_blocks_pruned = 0; std::vector<PoolBlock*> blocks_to_prune;
for (auto it = m_blocksByHeight.begin(); (it != m_blocksByHeight.end()) && (it->first <= h);) { for (auto it = m_blocksByHeight.begin(); (it != m_blocksByHeight.end()) && (it->first <= h);) {
const uint64_t height = it->first; const uint64_t height = it->first;
std::vector<PoolBlock*>& v = it->second; std::vector<PoolBlock*>& v = it->second;
v.erase(std::remove_if(v.begin(), v.end(), v.erase(std::remove_if(v.begin(), v.end(),
[this, prune_distance, cur_time, prune_delay, &num_blocks_pruned, height](PoolBlock* block) [this, prune_distance, cur_time, prune_delay, &blocks_to_prune, height](PoolBlock* block)
{ {
if ((block->m_depth >= prune_distance) || (cur_time >= block->m_localTimestamp + prune_delay)) { if ((block->m_depth >= prune_distance) || (cur_time >= block->m_localTimestamp + prune_delay)) {
auto it2 = m_blocksById.find(block->m_sidechainId); auto it2 = m_blocksById.find(block->m_sidechainId);
if (it2 != m_blocksById.end()) { if (it2 != m_blocksById.end()) {
m_blocksById.erase(it2); m_blocksById.erase(it2);
delete block; blocks_to_prune.push_back(block);
++num_blocks_pruned;
} }
else { else {
LOGERR(1, "m_blocksByHeight and m_blocksById are inconsistent at height " << height << ". Fix the code!"); LOGERR(1, "m_blocksByHeight and m_blocksById are inconsistent at height " << height << ". Fix the code!");
@ -2093,8 +2092,8 @@ void SideChain::prune_old_blocks()
} }
} }
if (num_blocks_pruned) { if (!blocks_to_prune.empty()) {
LOGINFO(4, "pruned " << num_blocks_pruned << " old blocks at heights <= " << h); LOGINFO(4, "pruned " << blocks_to_prune.size() << " old blocks at heights <= " << h);
// If side-chain started pruning blocks it means the initial sync is complete // If side-chain started pruning blocks it means the initial sync is complete
// It's now safe to delete cached blocks // It's now safe to delete cached blocks
@ -2105,6 +2104,11 @@ void SideChain::prune_old_blocks()
// Pre-calc workers are not needed anymore // Pre-calc workers are not needed anymore
finish_precalc(); finish_precalc();
// We can only delete old blocks after the precalc is stopped because it can still use some of them
for (const PoolBlock* b : blocks_to_prune) {
delete b;
}
#ifdef DEV_TEST_SYNC #ifdef DEV_TEST_SYNC
if (m_firstPruneTime == 0) { if (m_firstPruneTime == 0) {
m_firstPruneTime = seconds_since_epoch(); m_firstPruneTime = seconds_since_epoch();