diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt --- a/src/test/fuzz/CMakeLists.txt +++ b/src/test/fuzz/CMakeLists.txt @@ -91,6 +91,7 @@ key_io locale net_permissions + netaddress p2p_transport_deserializer parse_hd_keypath parse_iso8601 diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp new file mode 100644 --- /dev/null +++ b/src/test/fuzz/netaddress.cpp @@ -0,0 +1,136 @@ +// 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 + +namespace { +CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider) noexcept { + const Network network = fuzzed_data_provider.PickValueInArray( + {Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL, + Network::NET_ONION}); + if (network == Network::NET_IPV4) { + const in_addr v4_addr = { + .s_addr = fuzzed_data_provider.ConsumeIntegral()}; + return CNetAddr{v4_addr}; + } else if (network == Network::NET_IPV6) { + if (fuzzed_data_provider.remaining_bytes() < 16) { + return CNetAddr{}; + } + in6_addr v6_addr = {}; + memcpy(v6_addr.s6_addr, + fuzzed_data_provider.ConsumeBytes(16).data(), 16); + return CNetAddr{v6_addr, + fuzzed_data_provider.ConsumeIntegral()}; + } else if (network == Network::NET_INTERNAL) { + CNetAddr net_addr; + net_addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32)); + return net_addr; + } else if (network == Network::NET_ONION) { + CNetAddr net_addr; + net_addr.SetSpecial(fuzzed_data_provider.ConsumeBytesAsString(32)); + return net_addr; + } else { + assert(false); + } +} +}; // namespace + +void test_one_input(const std::vector &buffer) { + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + const CNetAddr net_addr = ConsumeNetAddr(fuzzed_data_provider); + for (int i = 0; i < 15; ++i) { + (void)net_addr.GetByte(i); + } + (void)net_addr.GetHash(); + (void)net_addr.GetNetClass(); + if (net_addr.GetNetwork() == Network::NET_IPV4) { + assert(net_addr.IsIPv4()); + } + if (net_addr.GetNetwork() == Network::NET_IPV6) { + assert(net_addr.IsIPv6()); + } + if (net_addr.GetNetwork() == Network::NET_ONION) { + assert(net_addr.IsTor()); + } + if (net_addr.GetNetwork() == Network::NET_INTERNAL) { + assert(net_addr.IsInternal()); + } + if (net_addr.GetNetwork() == Network::NET_UNROUTABLE) { + assert(!net_addr.IsRoutable()); + } + (void)net_addr.IsBindAny(); + if (net_addr.IsInternal()) { + assert(net_addr.GetNetwork() == Network::NET_INTERNAL); + } + if (net_addr.IsIPv4()) { + assert(net_addr.GetNetwork() == Network::NET_IPV4 || + net_addr.GetNetwork() == Network::NET_UNROUTABLE); + } + if (net_addr.IsIPv6()) { + assert(net_addr.GetNetwork() == Network::NET_IPV6 || + net_addr.GetNetwork() == Network::NET_UNROUTABLE); + } + (void)net_addr.IsLocal(); + if (net_addr.IsRFC1918() || net_addr.IsRFC2544() || net_addr.IsRFC6598() || + net_addr.IsRFC5737() || net_addr.IsRFC3927()) { + assert(net_addr.IsIPv4()); + } + (void)net_addr.IsRFC2544(); + 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()) { + assert(net_addr.IsIPv6()); + } + (void)net_addr.IsRFC3927(); + (void)net_addr.IsRFC3964(); + if (net_addr.IsRFC4193()) { + assert(net_addr.GetNetwork() == Network::NET_ONION || + net_addr.GetNetwork() == Network::NET_INTERNAL || + net_addr.GetNetwork() == Network::NET_UNROUTABLE); + } + (void)net_addr.IsRFC4380(); + (void)net_addr.IsRFC4843(); + (void)net_addr.IsRFC4862(); + (void)net_addr.IsRFC5737(); + (void)net_addr.IsRFC6052(); + (void)net_addr.IsRFC6145(); + (void)net_addr.IsRFC6598(); + (void)net_addr.IsRFC7343(); + if (!net_addr.IsRoutable()) { + assert(net_addr.GetNetwork() == Network::NET_UNROUTABLE || + net_addr.GetNetwork() == Network::NET_INTERNAL); + } + if (net_addr.IsTor()) { + assert(net_addr.GetNetwork() == Network::NET_ONION); + } + (void)net_addr.IsValid(); + (void)net_addr.ToString(); + (void)net_addr.ToStringIP(); + + const CSubNet sub_net{net_addr, + fuzzed_data_provider.ConsumeIntegral()}; + (void)sub_net.IsValid(); + (void)sub_net.ToString(); + + const CService service{net_addr, + fuzzed_data_provider.ConsumeIntegral()}; + (void)service.GetKey(); + (void)service.GetPort(); + (void)service.ToString(); + (void)service.ToStringIPPort(); + (void)service.ToStringPort(); + + const CNetAddr other_net_addr = ConsumeNetAddr(fuzzed_data_provider); + (void)net_addr.GetReachabilityFrom(&other_net_addr); + (void)sub_net.Match(other_net_addr); +} diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py --- a/test/fuzz/test_runner.py +++ b/test/fuzz/test_runner.py @@ -12,11 +12,6 @@ import subprocess import sys -# Fuzzers known to lack a seed corpus in -# https://github.com/Bitcoin-ABC/qa-assets/tree/master/fuzz_seed_corpus -FUZZERS_MISSING_CORPORA = [ -] - def main(): parser = argparse.ArgumentParser( @@ -92,6 +87,22 @@ logging.error("No fuzz targets selected") logging.info("Fuzz targets selected: {}".format(test_list_selection)) + test_list_seedless = [] + for t in test_list_selection: + corpus_path = os.path.join(args.seed_dir, t) + if not os.path.exists(corpus_path) or len( + os.listdir(corpus_path)) == 0: + test_list_seedless.append(t) + test_list_seedless.sort() + if test_list_seedless: + logging.info( + "Fuzzing harnesses lacking a seed corpus: {}".format( + " ".join(test_list_seedless) + ) + ) + logging.info( + "Please consider adding a fuzz seed corpus at https://github.com/Bitcoin-ABC/qa-assets") + try: help_output = subprocess.run( args=[ @@ -123,8 +134,7 @@ def run_once(*, corpus, test_list, test_dir, export_coverage, use_valgrind): for t in test_list: corpus_path = os.path.join(corpus, t) - if t in FUZZERS_MISSING_CORPORA: - os.makedirs(corpus_path, exist_ok=True) + os.makedirs(corpus_path, exist_ok=True) args = [ os.path.join(test_dir, t), '-runs=1',