diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2015-01-04 17:15:02 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2015-01-07 13:11:54 +0100 |
commit | 008138c04a3242b72dc5128ac3585b50ac44e84e (patch) | |
tree | 96a36ddacec72f7ac091707424b28c59f2da6080 | |
parent | 3022e7df2a3f2c6e9869877c189c7e7cea7d7b54 (diff) |
Bugfix: only track UTXO modification after lookup
Otherwise, if CCoinsViewCache::ModifyCoins throws an exception in between
setting hasModifier and constructing the CCoinsModifier, the cache ends up
in an inconsistent state, resulting in an assert failure in the next
modification.
Bug discovered by Wladimir J. van der Laan.
Rebased-From: 1c52aad540ec1370db60fd68fc3485413e3cb8e1
Github-Pull: #5597
-rw-r--r-- | src/coins.cpp | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/src/coins.cpp b/src/coins.cpp index c2e802c953..66919da11e 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -106,7 +106,6 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const { CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) { assert(!hasModifier); - hasModifier = true; std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())); if (ret.second) { if (!base->GetCoins(txid, ret.first->second.coins)) { @@ -247,7 +246,10 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const return tx.ComputePriority(dResult); } -CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {} +CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) { + assert(!cache.hasModifier); + cache.hasModifier = true; +} CCoinsModifier::~CCoinsModifier() { |