diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3cca3277f..c762b0b97 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1229,6 +1229,20 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) LOCK2(cs_main, cs_wallet); + // The Phase-1 loop below walks the ACTIVE chain (chainActive.Next) and sizes blockCms from + // pindex->GetHeight(), terminating only on pbi==pindex. If pindex was reorged OFF the active + // chain (a reorg landed while ThreadNotifyWallets drained its connect backlog with cs_main + // released), the loop never reaches pindex and, once the active tip passes pindex's height, it + // writes blockCms[h-startHeight] out of bounds -> heap overflow. Rebuilding witnesses for an + // abandoned block is meaningless; the ChainTip for the new active tip re-drives this. cs_main is + // held for the whole function, so this check cannot race the loop below. + if (pindex != chainActive[pindex->GetHeight()]) { + if (fZdebug) + LogPrintf("%s: pindex height=%d not on active chain (reorg); skipping witness rebuild\n", + __func__, pindex->GetHeight()); + return; + } + int startHeight = VerifyAndSetInitialWitness(pindex, witnessOnly) + 1; if (startHeight > pindex->GetHeight() || witnessOnly) {