Skip to content

Commit 5518eee

Browse files
author
MarcoFalke
committed
Merge bitcoin#18047: tests: Add basic fuzzing harness for CNetAddr/CService/CSubNet related functions (netaddress.h)
6590395 tests: Remove FUZZERS_MISSING_CORPORA (practicalswift) 815c7a6 tests: Add basic fuzzing harness for CNetAddr/CService/CSubNet related functions (netaddress.h) (practicalswift) Pull request description: Add basic fuzzing harness for `CNetAddr`/`CService`/`CSubNet` related functions (`netaddress.h`). To test this PR: ``` $ make distclean $ ./autogen.sh $ CC=clang CXX=clang++ ./configure --enable-fuzz \ --with-sanitizers=address,fuzzer,undefined $ make $ src/test/fuzz/netaddress … ``` Top commit has no ACKs. Tree-SHA512: 69dc0e391d56d5e9cdb818ac0ac4b69445d0195f714442a06cf662998e38b6e0bbaa635dce78df37ba797feed633e94abba4764b946c1716d392756e7809112d
2 parents be00ef2 + 6590395 commit 5518eee

File tree

3 files changed

+145
-6
lines changed

3 files changed

+145
-6
lines changed

src/Makefile.test.include

+7
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ FUZZ_TARGETS = \
4242
test/fuzz/merkle_block_deserialize \
4343
test/fuzz/messageheader_deserialize \
4444
test/fuzz/netaddr_deserialize \
45+
test/fuzz/netaddress \
4546
test/fuzz/out_point_deserialize \
4647
test/fuzz/p2p_transport_deserializer \
4748
test/fuzz/parse_hd_keypath \
@@ -475,6 +476,12 @@ test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
475476
test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
476477
test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
477478

479+
test_fuzz_netaddress_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
480+
test_fuzz_netaddress_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
481+
test_fuzz_netaddress_LDADD = $(FUZZ_SUITE_LD_COMMON)
482+
test_fuzz_netaddress_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
483+
test_fuzz_netaddress_SOURCES = $(FUZZ_SUITE) test/fuzz/netaddress.cpp
484+
478485
test_fuzz_out_point_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DOUT_POINT_DESERIALIZE=1
479486
test_fuzz_out_point_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
480487
test_fuzz_out_point_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/test/fuzz/netaddress.cpp

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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 <netaddress.h>
6+
#include <test/fuzz/FuzzedDataProvider.h>
7+
#include <test/fuzz/fuzz.h>
8+
9+
#include <cassert>
10+
#include <cstdint>
11+
#include <netinet/in.h>
12+
#include <vector>
13+
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+
43+
void test_one_input(const std::vector<uint8_t>& buffer)
44+
{
45+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
46+
47+
const CNetAddr net_addr = ConsumeNetAddr(fuzzed_data_provider);
48+
for (int i = 0; i < 15; ++i) {
49+
(void)net_addr.GetByte(i);
50+
}
51+
(void)net_addr.GetHash();
52+
(void)net_addr.GetNetClass();
53+
if (net_addr.GetNetwork() == Network::NET_IPV4) {
54+
assert(net_addr.IsIPv4());
55+
}
56+
if (net_addr.GetNetwork() == Network::NET_IPV6) {
57+
assert(net_addr.IsIPv6());
58+
}
59+
if (net_addr.GetNetwork() == Network::NET_ONION) {
60+
assert(net_addr.IsTor());
61+
}
62+
if (net_addr.GetNetwork() == Network::NET_INTERNAL) {
63+
assert(net_addr.IsInternal());
64+
}
65+
if (net_addr.GetNetwork() == Network::NET_UNROUTABLE) {
66+
assert(!net_addr.IsRoutable());
67+
}
68+
(void)net_addr.IsBindAny();
69+
if (net_addr.IsInternal()) {
70+
assert(net_addr.GetNetwork() == Network::NET_INTERNAL);
71+
}
72+
if (net_addr.IsIPv4()) {
73+
assert(net_addr.GetNetwork() == Network::NET_IPV4 || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
74+
}
75+
if (net_addr.IsIPv6()) {
76+
assert(net_addr.GetNetwork() == Network::NET_IPV6 || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
77+
}
78+
(void)net_addr.IsLocal();
79+
if (net_addr.IsRFC1918() || net_addr.IsRFC2544() || net_addr.IsRFC6598() || net_addr.IsRFC5737() || net_addr.IsRFC3927()) {
80+
assert(net_addr.IsIPv4());
81+
}
82+
(void)net_addr.IsRFC2544();
83+
if (net_addr.IsRFC3849() || net_addr.IsRFC3964() || net_addr.IsRFC4380() || net_addr.IsRFC4843() || net_addr.IsRFC7343() || net_addr.IsRFC4862() || net_addr.IsRFC6052() || net_addr.IsRFC6145()) {
84+
assert(net_addr.IsIPv6());
85+
}
86+
(void)net_addr.IsRFC3927();
87+
(void)net_addr.IsRFC3964();
88+
if (net_addr.IsRFC4193()) {
89+
assert(net_addr.GetNetwork() == Network::NET_ONION || net_addr.GetNetwork() == Network::NET_INTERNAL || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
90+
}
91+
(void)net_addr.IsRFC4380();
92+
(void)net_addr.IsRFC4843();
93+
(void)net_addr.IsRFC4862();
94+
(void)net_addr.IsRFC5737();
95+
(void)net_addr.IsRFC6052();
96+
(void)net_addr.IsRFC6145();
97+
(void)net_addr.IsRFC6598();
98+
(void)net_addr.IsRFC7343();
99+
if (!net_addr.IsRoutable()) {
100+
assert(net_addr.GetNetwork() == Network::NET_UNROUTABLE || net_addr.GetNetwork() == Network::NET_INTERNAL);
101+
}
102+
if (net_addr.IsTor()) {
103+
assert(net_addr.GetNetwork() == Network::NET_ONION);
104+
}
105+
(void)net_addr.IsValid();
106+
(void)net_addr.ToString();
107+
(void)net_addr.ToStringIP();
108+
109+
const CSubNet sub_net{net_addr, fuzzed_data_provider.ConsumeIntegral<int32_t>()};
110+
(void)sub_net.IsValid();
111+
(void)sub_net.ToString();
112+
113+
const CService service{net_addr, fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
114+
(void)service.GetKey();
115+
(void)service.GetPort();
116+
(void)service.ToString();
117+
(void)service.ToStringIPPort();
118+
(void)service.ToStringPort();
119+
120+
const CNetAddr other_net_addr = ConsumeNetAddr(fuzzed_data_provider);
121+
(void)net_addr.GetReachabilityFrom(&other_net_addr);
122+
(void)sub_net.Match(other_net_addr);
123+
}

test/fuzz/test_runner.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212
import subprocess
1313
import logging
1414

15-
# Fuzzers known to lack a seed corpus in https://github.com/bitcoin-core/qa-assets/tree/master/fuzz_seed_corpus
16-
FUZZERS_MISSING_CORPORA = [
17-
]
18-
1915

2016
def main():
2117
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
@@ -94,6 +90,20 @@ def main():
9490

9591
logging.info("{} of {} detected fuzz target(s) selected: {}".format(len(test_list_selection), len(test_list_all), " ".join(test_list_selection)))
9692

93+
test_list_seedless = []
94+
for t in test_list_selection:
95+
corpus_path = os.path.join(args.seed_dir, t)
96+
if not os.path.exists(corpus_path) or len(os.listdir(corpus_path)) == 0:
97+
test_list_seedless.append(t)
98+
test_list_seedless.sort()
99+
if test_list_seedless:
100+
logging.info(
101+
"Fuzzing harnesses lacking a seed corpus: {}".format(
102+
" ".join(test_list_seedless)
103+
)
104+
)
105+
logging.info("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets")
106+
97107
try:
98108
help_output = subprocess.run(
99109
args=[
@@ -124,8 +134,7 @@ def main():
124134
def run_once(*, corpus, test_list, build_dir, export_coverage, use_valgrind):
125135
for t in test_list:
126136
corpus_path = os.path.join(corpus, t)
127-
if t in FUZZERS_MISSING_CORPORA:
128-
os.makedirs(corpus_path, exist_ok=True)
137+
os.makedirs(corpus_path, exist_ok=True)
129138
args = [
130139
os.path.join(build_dir, 'src', 'test', 'fuzz', t),
131140
'-runs=1',

0 commit comments

Comments
 (0)