diff options
author | merge-script <falke.marco@gmail.com> | 2021-09-21 18:21:00 +0200 |
---|---|---|
committer | merge-script <falke.marco@gmail.com> | 2021-09-21 18:21:00 +0200 |
commit | a8a272ac329da679bd489e272ed1773147f59eb9 (patch) | |
tree | 21ea162b00629318af31f930351e9a40907d91d4 /src/addrman.cpp | |
parent | ae674a0198b06169eb3b27f86cf6755fecde4107 (diff) | |
parent | fa3669f72f69662049b55ad1a482b4a0f9f7ae40 (diff) | |
download | bitcoin-a8a272ac329da679bd489e272ed1773147f59eb9.tar.xz |
Merge bitcoin/bitcoin#22734: addrman: Avoid crash on corrupt data, Force Check after deserialize
fa3669f72f69662049b55ad1a482b4a0f9f7ae40 fuzz: Move all addrman fuzz targets to one file (MarcoFalke)
fa7a883f5a219d5f3c2f992b090db4e6c279db12 addrman: Replace assert with throw on corrupt data (MarcoFalke)
fa298971e6890715e2b0b93f2a7f445d32d6622f Refactor: Turn the internal addrman check helper into a forced check (MarcoFalke)
fae5c633dc05a045aaac370b383e4799cb0e0590 move-only: Move CAddrMan::Check to cpp file (MarcoFalke)
Pull request description:
Assert should only be used for program internal logic errors, not to sanitize external user input.
The assert was introduced via the debug-only runtime option `-checkaddrman` in commit 803ef70fd9f65ef800567ff9456fac525bc3e3c2, thus won't need a backport.
Also, it doesn't really make sense to continue when the deserialized addrman doesn't pass the sanity check.
For example, if `nLastSuccess` is negative, it would later result in integer overflows. Thus, this patch fixes #22931.
Also,
Fixes #22503
Fixes #22504
Fixes #22519
Closes #22498
Steps to test:
```
mkdir -p /tmp/test_235/regtest/
echo 'H4sIAAAAAAAAA/u1f+stZmUGYgELgwPRakfBKBgFo2AUjIJRMApGwSgYBaNgFIyCUTBswdyGpFnLjUKjP9e0bvjYusl6b+L2e7Vs2dd6N//Pua0/xQUALJAn93IQAAA=' | base64 --decode | zcat > /tmp/test_235/regtest/peers.dat
./src/qt/bitcoin-qt -regtest -datadir=/tmp/test_235/ -checkaddrman=1 -printtoconsole | grep -A2 'Loading P2P addresses'
```
Output before:
```
2021-09-10T11:28:37Z init message: Loading P2P addresses…
2021-09-10T11:28:37Z ADDRMAN CONSISTENCY CHECK FAILED!!! err=-16
bitcoin-qt: addrman.cpp:765: void CAddrMan::Check() const: Assertion `false' failed.
(program crashes)
```
Output after:
```
2021-09-10T11:26:00Z init message: Loading P2P addresses…
2021-09-10T11:26:00Z Error: Invalid or corrupt peers.dat (Corrupt data. Consistency check failed with code -16: iostream error). If you believe this is a bug, please report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file ("/tmp/test_235/regtest/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.
(program exits)
```
ACKs for top commit:
naumenkogs:
ACK fa3669f72f69662049b55ad1a482b4a0f9f7ae40
jnewbery:
Code review ACK fa3669f72f69662049b55ad1a482b4a0f9f7ae40
vasild:
ACK fa3669f72f69662049b55ad1a482b4a0f9f7ae40
Tree-SHA512: 687e4a4765bbc66495152fa7a49d28ee84b405dc5370ba87b4016b5593e45f54c4ce5cae579e4d433e0e082d20fc263969fa602679c911accef0adb2d6213bd6
Diffstat (limited to 'src/addrman.cpp')
-rw-r--r-- | src/addrman.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/src/addrman.cpp b/src/addrman.cpp index a1e8cb1bf1..7c6b8fe64d 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -386,7 +386,12 @@ void CAddrMan::Unserialize(Stream& s_) LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions or invalid addresses\n", nLostUnk, nLost); } - Check(); + const int check_code{ForceCheckAddrman()}; + if (check_code != 0) { + throw std::ios_base::failure(strprintf( + "Corrupt data. Consistency check failed with code %s", + check_code)); + } } // explicit instantiation @@ -743,13 +748,24 @@ CAddrInfo CAddrMan::Select_(bool newOnly) const } } -int CAddrMan::Check_() const +void CAddrMan::Check() const { AssertLockHeld(cs); // Run consistency checks 1 in m_consistency_check_ratio times if enabled - if (m_consistency_check_ratio == 0) return 0; - if (insecure_rand.randrange(m_consistency_check_ratio) >= 1) return 0; + if (m_consistency_check_ratio == 0) return; + if (insecure_rand.randrange(m_consistency_check_ratio) >= 1) return; + + const int err{ForceCheckAddrman()}; + if (err) { + LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err); + assert(false); + } +} + +int CAddrMan::ForceCheckAddrman() const +{ + AssertLockHeld(cs); LogPrint(BCLog::ADDRMAN, "Addrman checks started: new %i, tried %i, total %u\n", nNew, nTried, vRandom.size()); |