From e6bb9fde851422808f5d9870782c394f74a1f400 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 24 May 2020 18:11:55 +0000 Subject: [PATCH 1/2] tests: Add fuzzing harness for CAddrMan --- src/Makefile.test.include | 7 +++ src/test/fuzz/addrman.cpp | 119 ++++++++++++++++++++++++++++++++++++++ src/test/fuzz/util.h | 14 +++++ 3 files changed, 140 insertions(+) create mode 100644 src/test/fuzz/addrman.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 157b62cef5f..9cc383c240d 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -7,6 +7,7 @@ FUZZ_TARGETS = \ test/fuzz/addr_info_deserialize \ test/fuzz/addrdb \ test/fuzz/address_deserialize \ + test/fuzz/addrman \ test/fuzz/addrman_deserialize \ test/fuzz/asmap \ test/fuzz/asmap_direct \ @@ -353,6 +354,12 @@ test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_address_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) test_fuzz_address_deserialize_SOURCES = test/fuzz/deserialize.cpp +test_fuzz_addrman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_addrman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_addrman_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_addrman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) +test_fuzz_addrman_SOURCES = test/fuzz/addrman.cpp + test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1 test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp new file mode 100644 index 00000000000..0ceeea2d364 --- /dev/null +++ b/src/test/fuzz/addrman.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2020 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void initialize() +{ + SelectParams(CBaseChainParams::REGTEST); +} + +void test_one_input(const std::vector& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + SetMockTime(ConsumeTime(fuzzed_data_provider)); + CAddrMan addr_man; + if (fuzzed_data_provider.ConsumeBool()) { + addr_man.m_asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); + if (!SanityCheckASMap(addr_man.m_asmap)) { + addr_man.m_asmap.clear(); + } + } + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 11)) { + case 0: { + addr_man.Clear(); + break; + } + case 1: { + addr_man.ResolveCollisions(); + break; + } + case 2: { + (void)addr_man.SelectTriedCollision(); + break; + } + case 3: { + (void)addr_man.Select(fuzzed_data_provider.ConsumeBool()); + break; + } + case 4: { + (void)addr_man.GetAddr(fuzzed_data_provider.ConsumeIntegralInRange(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange(0, 4096)); + break; + } + case 5: { + const std::optional opt_address = ConsumeDeserializable(fuzzed_data_provider); + const std::optional opt_net_addr = ConsumeDeserializable(fuzzed_data_provider); + if (opt_address && opt_net_addr) { + addr_man.Add(*opt_address, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange(0, 100000000)); + } + break; + } + case 6: { + std::vector addresses; + while (fuzzed_data_provider.ConsumeBool()) { + const std::optional opt_address = ConsumeDeserializable(fuzzed_data_provider); + if (!opt_address) { + break; + } + addresses.push_back(*opt_address); + } + const std::optional opt_net_addr = ConsumeDeserializable(fuzzed_data_provider); + if (opt_net_addr) { + addr_man.Add(addresses, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange(0, 100000000)); + } + break; + } + case 7: { + const std::optional opt_service = ConsumeDeserializable(fuzzed_data_provider); + if (opt_service) { + addr_man.Good(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 8: { + const std::optional opt_service = ConsumeDeserializable(fuzzed_data_provider); + if (opt_service) { + addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 9: { + const std::optional opt_service = ConsumeDeserializable(fuzzed_data_provider); + if (opt_service) { + addr_man.Connected(*opt_service, ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 10: { + const std::optional opt_service = ConsumeDeserializable(fuzzed_data_provider); + if (opt_service) { + addr_man.SetServices(*opt_service, ServiceFlags{fuzzed_data_provider.ConsumeIntegral()}); + } + break; + } + case 11: { + (void)addr_man.Check(); + break; + } + } + } + (void)addr_man.size(); + CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION); + data_stream << addr_man; +} diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index fec6e13e863..e99ed8d72d3 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -39,6 +41,11 @@ NODISCARD inline std::vector ConsumeRandomLengthByteVector(FuzzedDataPr return {s.begin(), s.end()}; } +NODISCARD inline std::vector ConsumeRandomLengthBitVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +{ + return BytesToBits(ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length)); +} + NODISCARD inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { return {ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION}; @@ -89,6 +96,13 @@ NODISCARD inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) return fuzzed_data_provider.ConsumeIntegralInRange(0, MAX_MONEY); } +NODISCARD inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + static const int64_t time_min = ParseISO8601DateTime("1970-01-01T00:00:00Z"); + static const int64_t time_max = ParseISO8601DateTime("9999-12-31T23:59:59Z"); + return fuzzed_data_provider.ConsumeIntegralInRange(time_min, time_max); +} + NODISCARD inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept { const std::vector b = ConsumeRandomLengthByteVector(fuzzed_data_provider); From d04a17a7907c57f7b570e1b9743fd63489bdad68 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Thu, 12 Nov 2020 14:09:09 +0000 Subject: [PATCH 2/2] fuzz: Use ConsumeRandomLengthBitVector(...) in src/test/fuzz/connman and src/test/fuzz/net --- src/test/fuzz/connman.cpp | 2 +- src/test/fuzz/net.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index bb9d28a4abe..6521c3f3b20 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -117,7 +117,7 @@ void test_one_input(const std::vector& buffer) connman.RemoveAddedNode(random_string); break; case 24: { - const std::vector asmap = ConsumeRandomLengthIntegralVector(fuzzed_data_provider, 512); + const std::vector asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); if (SanityCheckASMap(asmap)) { connman.SetAsmap(asmap); } diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 38188387658..c61d4062918 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -63,7 +63,7 @@ void test_one_input(const std::vector& buffer) break; } case 3: { - const std::vector asmap = ConsumeRandomLengthIntegralVector(fuzzed_data_provider, 128); + const std::vector asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); if (!SanityCheckASMap(asmap)) { break; }