From 8153bd9247dad3982d54488bcdb3960470315290 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Wed, 2 Feb 2022 09:47:13 -0500 Subject: [PATCH] blockmanager: avoid undefined behavior during FlushBlockFile If we call FlushBlockFile() without having intitialized the block index with LoadBlockIndexDB(), we may be indexing into an empty vector. Specifically this is an issue when we call MaybeRebalanceCaches() during chainstate init before the block index has been loaded, which calls FlushBlockFile(). Also add an assert to avoid undefined behavior. Co-authored-by: Russell Yanofsky --- src/node/blockstorage.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 57f81e6bb6..9fea644f05 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -524,6 +524,16 @@ void BlockManager::FlushUndoFile(int block_file, bool finalize) void BlockManager::FlushBlockFile(bool fFinalize, bool finalize_undo) { LOCK(cs_LastBlockFile); + + if (m_blockfile_info.size() < 1) { + // Return if we haven't loaded any blockfiles yet. This happens during + // chainstate init, when we call ChainstateManager::MaybeRebalanceCaches() (which + // then calls FlushStateToDisk()), resulting in a call to this function before we + // have populated `m_blockfile_info` via LoadBlockIndexDB(). + return; + } + assert(static_cast(m_blockfile_info.size()) > m_last_blockfile); + FlatFilePos block_pos_old(m_last_blockfile, m_blockfile_info[m_last_blockfile].nSize); if (!BlockFileSeq().Flush(block_pos_old, fFinalize)) { AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error.");