aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/addrman.cpp24
-rw-r--r--src/addrman.h18
-rw-r--r--src/test/fuzz/addrman.cpp11
-rw-r--r--src/test/fuzz/data_stream.cpp30
-rwxr-xr-xtest/functional/feature_addrman.py11
6 files changed, 46 insertions, 49 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index a85a359960..be63214c23 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -232,7 +232,6 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
test/fuzz/crypto_poly1305.cpp \
test/fuzz/cuckoocache.cpp \
- test/fuzz/data_stream.cpp \
test/fuzz/decode_tx.cpp \
test/fuzz/descriptor_parse.cpp \
test/fuzz/deserialize.cpp \
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());
diff --git a/src/addrman.h b/src/addrman.h
index 0885231ebc..7dd8528bef 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -391,20 +391,12 @@ private:
//! Return a random to-be-evicted tried table address.
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
- //! Consistency check
- void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs)
- {
- AssertLockHeld(cs);
-
- const int err = Check_();
- if (err) {
- LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
- assert(false);
- }
- }
+ //! Consistency check, taking into account m_consistency_check_ratio. Will std::abort if an inconsistency is detected.
+ void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);
- //! Perform consistency check. Returns an error code or zero.
- int Check_() const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ //! Perform consistency check, regardless of m_consistency_check_ratio.
+ //! @returns an error code or zero.
+ int ForceCheckAddrman() const EXCLUSIVE_LOCKS_REQUIRED(cs);
/**
* Return all or many randomly selected addresses, optionally by network.
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index 95c5a99c1b..45ee778b87 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -23,6 +23,17 @@ void initialize_addrman()
SelectParams(CBaseChainParams::REGTEST);
}
+FUZZ_TARGET_INIT(data_stream_addr_man, initialize_addrman)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ CDataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
+ CAddrMan addr_man(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0);
+ try {
+ ReadFromStream(addr_man, data_stream);
+ } catch (const std::exception&) {
+ }
+}
+
class CAddrManDeterministic : public CAddrMan
{
public:
diff --git a/src/test/fuzz/data_stream.cpp b/src/test/fuzz/data_stream.cpp
deleted file mode 100644
index 323090e041..0000000000
--- a/src/test/fuzz/data_stream.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <addrdb.h>
-#include <addrman.h>
-#include <net.h>
-#include <test/fuzz/FuzzedDataProvider.h>
-#include <test/fuzz/fuzz.h>
-#include <test/fuzz/util.h>
-#include <test/util/setup_common.h>
-
-#include <cstdint>
-#include <vector>
-
-void initialize_data_stream_addr_man()
-{
- static const auto testing_setup = MakeNoLogFileContext<>();
-}
-
-FUZZ_TARGET_INIT(data_stream_addr_man, initialize_data_stream_addr_man)
-{
- FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
- CDataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
- CAddrMan addr_man(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0);
- try {
- ReadFromStream(addr_man, data_stream);
- } catch (const std::exception&) {
- }
-}
diff --git a/test/functional/feature_addrman.py b/test/functional/feature_addrman.py
index 42afd74ac9..55d3e48c64 100755
--- a/test/functional/feature_addrman.py
+++ b/test/functional/feature_addrman.py
@@ -19,6 +19,7 @@ def serialize_addrman(
format=1,
lowest_compatible=3,
net_magic="regtest",
+ bucket_key=1,
len_new=None,
len_tried=None,
mock_checksum=None,
@@ -29,7 +30,7 @@ def serialize_addrman(
r = MAGIC_BYTES[net_magic]
r += struct.pack("B", format)
r += struct.pack("B", INCOMPATIBILITY_BASE + lowest_compatible)
- r += ser_uint256(1)
+ r += ser_uint256(bucket_key)
r += struct.pack("i", len_new or len(new))
r += struct.pack("i", len_tried or len(tried))
ADDRMAN_NEW_BUCKET_COUNT = 1 << 10
@@ -119,6 +120,14 @@ class AddrmanTest(BitcoinTestFramework):
match=ErrorMatch.FULL_REGEX,
)
+ self.log.info("Check that corrupt addrman cannot be read (failed check)")
+ self.stop_node(0)
+ write_addrman(peers_dat, bucket_key=0)
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg=init_error("Corrupt data. Consistency check failed with code -16: .*"),
+ match=ErrorMatch.FULL_REGEX,
+ )
+
self.log.info("Check that missing addrman is recreated")
self.stop_node(0)
os.remove(peers_dat)