Skip to content

Commit a426317

Browse files
author
MarcoFalke
committed
Merge #19222: tests: Add fuzzing harness for BanMan
97846d7 tests: Add fuzzing harness for BanMan (practicalswift) deba199 tests: Add ConsumeSubNet(...). Move and increase coverage in ConsumeNetAddr(...). (practicalswift) Pull request description: Add fuzzing harness for `BanMan`. See [`doc/fuzzing.md`](https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md) for information on how to fuzz Bitcoin Core. Don't forget to contribute any coverage increasing inputs you find to the [Bitcoin Core fuzzing corpus repo](https://github.com/bitcoin-core/qa-assets). Happy fuzzing :) Top commit has no ACKs. Tree-SHA512: f4126c15bbb77638833367d73f58193c8f05d16bed0b1d6c33b39387d5b610ff34af78cd721adb51778062ce3ac5e79756d1c3895ef54c6c80c61dcf056e94ff
2 parents ca05588 + 97846d7 commit a426317

File tree

4 files changed

+132
-29
lines changed

4 files changed

+132
-29
lines changed

src/Makefile.test.include

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ FUZZ_TARGETS = \
1111
test/fuzz/asmap \
1212
test/fuzz/asmap_direct \
1313
test/fuzz/banentry_deserialize \
14+
test/fuzz/banman \
1415
test/fuzz/base_encode_decode \
1516
test/fuzz/bech32 \
1617
test/fuzz/block \
@@ -355,6 +356,12 @@ test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
355356
test_fuzz_banentry_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
356357
test_fuzz_banentry_deserialize_SOURCES = test/fuzz/deserialize.cpp
357358

359+
test_fuzz_banman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
360+
test_fuzz_banman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
361+
test_fuzz_banman_LDADD = $(FUZZ_SUITE_LD_COMMON)
362+
test_fuzz_banman_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
363+
test_fuzz_banman_SOURCES = test/fuzz/banman.cpp
364+
358365
test_fuzz_base_encode_decode_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
359366
test_fuzz_base_encode_decode_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
360367
test_fuzz_base_encode_decode_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/test/fuzz/banman.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <banman.h>
6+
#include <fs.h>
7+
#include <netaddress.h>
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
#include <util/system.h>
12+
13+
#include <cstdint>
14+
#include <limits>
15+
#include <string>
16+
#include <vector>
17+
18+
namespace {
19+
int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
20+
{
21+
// Avoid signed integer overflow by capping to int32_t max:
22+
// banman.cpp:137:73: runtime error: signed integer overflow: 1591700817 + 9223372036854775807 cannot be represented in type 'long'
23+
return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::max());
24+
}
25+
} // namespace
26+
27+
void initialize()
28+
{
29+
InitializeFuzzingContext();
30+
}
31+
32+
void test_one_input(const std::vector<uint8_t>& buffer)
33+
{
34+
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
35+
const fs::path banlist_file = GetDataDir() / "fuzzed_banlist.dat";
36+
fs::remove(banlist_file);
37+
{
38+
BanMan ban_man{banlist_file, nullptr, ConsumeBanTimeOffset(fuzzed_data_provider)};
39+
while (fuzzed_data_provider.ConsumeBool()) {
40+
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) {
41+
case 0: {
42+
ban_man.Ban(ConsumeNetAddr(fuzzed_data_provider),
43+
ConsumeBanTimeOffset(fuzzed_data_provider), fuzzed_data_provider.ConsumeBool());
44+
break;
45+
}
46+
case 1: {
47+
ban_man.Ban(ConsumeSubNet(fuzzed_data_provider),
48+
ConsumeBanTimeOffset(fuzzed_data_provider), fuzzed_data_provider.ConsumeBool());
49+
break;
50+
}
51+
case 2: {
52+
ban_man.ClearBanned();
53+
break;
54+
}
55+
case 4: {
56+
ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider));
57+
break;
58+
}
59+
case 5: {
60+
ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider));
61+
break;
62+
}
63+
case 6: {
64+
ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider));
65+
break;
66+
}
67+
case 7: {
68+
ban_man.Unban(ConsumeSubNet(fuzzed_data_provider));
69+
break;
70+
}
71+
case 8: {
72+
banmap_t banmap;
73+
ban_man.GetBanned(banmap);
74+
break;
75+
}
76+
case 9: {
77+
ban_man.DumpBanlist();
78+
break;
79+
}
80+
case 11: {
81+
ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider));
82+
break;
83+
}
84+
}
85+
}
86+
}
87+
fs::remove(banlist_file);
88+
}

src/test/fuzz/netaddress.cpp

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,13 @@
55
#include <netaddress.h>
66
#include <test/fuzz/FuzzedDataProvider.h>
77
#include <test/fuzz/fuzz.h>
8+
#include <test/fuzz/util.h>
89

910
#include <cassert>
1011
#include <cstdint>
1112
#include <netinet/in.h>
1213
#include <vector>
1314

14-
namespace {
15-
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
16-
{
17-
const Network network = fuzzed_data_provider.PickValueInArray({Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL, Network::NET_ONION});
18-
if (network == Network::NET_IPV4) {
19-
const in_addr v4_addr = {
20-
.s_addr = fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
21-
return CNetAddr{v4_addr};
22-
} else if (network == Network::NET_IPV6) {
23-
if (fuzzed_data_provider.remaining_bytes() < 16) {
24-
return CNetAddr{};
25-
}
26-
in6_addr v6_addr = {};
27-
memcpy(v6_addr.s6_addr, fuzzed_data_provider.ConsumeBytes<uint8_t>(16).data(), 16);
28-
return CNetAddr{v6_addr, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
29-
} else if (network == Network::NET_INTERNAL) {
30-
CNetAddr net_addr;
31-
net_addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32));
32-
return net_addr;
33-
} else if (network == Network::NET_ONION) {
34-
CNetAddr net_addr;
35-
net_addr.SetSpecial(fuzzed_data_provider.ConsumeBytesAsString(32));
36-
return net_addr;
37-
} else {
38-
assert(false);
39-
}
40-
}
41-
}; // namespace
42-
4315
void test_one_input(const std::vector<uint8_t>& buffer)
4416
{
4517
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());

src/test/fuzz/util.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@
88
#include <amount.h>
99
#include <arith_uint256.h>
1010
#include <attributes.h>
11+
#include <chainparamsbase.h>
1112
#include <coins.h>
1213
#include <consensus/consensus.h>
14+
#include <netaddress.h>
15+
#include <netbase.h>
1316
#include <primitives/transaction.h>
1417
#include <script/script.h>
1518
#include <script/standard.h>
1619
#include <serialize.h>
1720
#include <streams.h>
1821
#include <test/fuzz/FuzzedDataProvider.h>
1922
#include <test/fuzz/fuzz.h>
23+
#include <test/util/setup_common.h>
2024
#include <txmempool.h>
2125
#include <uint256.h>
2226
#include <version.h>
@@ -228,4 +232,36 @@ NODISCARD inline std::vector<uint8_t> ConsumeFixedLengthByteVector(FuzzedDataPro
228232
return result;
229233
}
230234

235+
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
236+
{
237+
const Network network = fuzzed_data_provider.PickValueInArray({Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL, Network::NET_ONION});
238+
CNetAddr net_addr;
239+
if (network == Network::NET_IPV4) {
240+
const in_addr v4_addr = {
241+
.s_addr = fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
242+
net_addr = CNetAddr{v4_addr};
243+
} else if (network == Network::NET_IPV6) {
244+
if (fuzzed_data_provider.remaining_bytes() >= 16) {
245+
in6_addr v6_addr = {};
246+
memcpy(v6_addr.s6_addr, fuzzed_data_provider.ConsumeBytes<uint8_t>(16).data(), 16);
247+
net_addr = CNetAddr{v6_addr, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
248+
}
249+
} else if (network == Network::NET_INTERNAL) {
250+
net_addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32));
251+
} else if (network == Network::NET_ONION) {
252+
net_addr.SetSpecial(fuzzed_data_provider.ConsumeBytesAsString(32));
253+
}
254+
return net_addr;
255+
}
256+
257+
CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept
258+
{
259+
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>()};
260+
}
261+
262+
void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST)
263+
{
264+
static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};
265+
}
266+
231267
#endif // BITCOIN_TEST_FUZZ_UTIL_H

0 commit comments

Comments
 (0)