diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt index 3defde5e1..365e5da3d 100644 --- a/src/test/fuzz/CMakeLists.txt +++ b/src/test/fuzz/CMakeLists.txt @@ -1,222 +1,223 @@ # Fuzzer test harness add_custom_target(bitcoin-fuzzers) define_property(GLOBAL PROPERTY FUZZ_TARGETS BRIEF_DOCS "List of fuzz targets" FULL_DOCS "A list of the fuzz targets" ) set_property(GLOBAL APPEND PROPERTY FUZZ_TARGETS bitcoin-fuzzers) include(InstallationHelper) macro(add_fuzz_target TARGET EXE_NAME) add_executable(${TARGET} EXCLUDE_FROM_ALL fuzz.cpp ${ARGN} ) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${EXE_NAME}) target_link_libraries(${TARGET} server testutil rpcclient) if(TARGET bitcoinconsensus-shared) target_link_libraries(${TARGET} bitcoinconsensus-shared) else() target_link_libraries(${TARGET} bitcoinconsensus) endif() add_dependencies(bitcoin-fuzzers ${TARGET}) set_property(GLOBAL APPEND PROPERTY FUZZ_TARGETS ${TARGET}) install_target(${TARGET} COMPONENT fuzzer EXCLUDE_FROM_ALL ) endmacro() function(add_regular_fuzz_targets) foreach(_fuzz_test_name ${ARGN}) sanitize_target_name("fuzz-" ${_fuzz_test_name} _fuzz_target_name) add_fuzz_target( ${_fuzz_target_name} ${_fuzz_test_name} # Sources "${_fuzz_test_name}.cpp" ) endforeach() endfunction() include(SanitizeHelper) function(add_deserialize_fuzz_targets) foreach(_fuzz_test_name ${ARGN}) sanitize_target_name("fuzz-" ${_fuzz_test_name} _fuzz_target_name) add_fuzz_target( ${_fuzz_target_name} ${_fuzz_test_name} # Sources deserialize.cpp ) sanitize_c_cxx_definition("" ${_fuzz_test_name} _target_definition) string(TOUPPER ${_target_definition} _target_definition) target_compile_definitions(${_fuzz_target_name} PRIVATE ${_target_definition}) endforeach() endfunction() function(add_process_message_fuzz_targets) foreach(_fuzz_test_name ${ARGN}) sanitize_target_name("fuzz-process_message_" ${_fuzz_test_name} _fuzz_target_name) add_fuzz_target( ${_fuzz_target_name} process_message_${_fuzz_test_name} # Sources process_message.cpp ) target_compile_definitions(${_fuzz_target_name} PRIVATE MESSAGE_TYPE=${_fuzz_test_name}) endforeach() endfunction() add_regular_fuzz_targets( addition_overflow addrdb asmap asmap_direct + banman base_encode_decode block block_header blockfilter bloom_filter cashaddr chain checkqueue coins_view crypto crypto_common cuckoocache descriptor_parse eval_script fee_rate fees flatfile float golomb_rice hex http_request integer key key_io kitchen_sink locale merkleblock message multiplication_overflow net_permissions netaddress p2p_transport_deserializer parse_hd_keypath parse_iso8601 parse_numbers parse_script parse_univalue prevector pow primitives_transaction process_message process_messages protocol psbt random rolling_bloom_filter script script_bitcoin_consensus script_descriptor_cache script_flags script_interpreter script_ops script_sigcache script_sign scriptnum_ops signature_checker span spanparsing string strprintf system timedata transaction tx_in tx_out ) add_deserialize_fuzz_targets( addr_info_deserialize address_deserialize addrman_deserialize banentry_deserialize block_deserialize block_file_info_deserialize block_filter_deserialize block_header_and_short_txids_deserialize blockheader_deserialize blocklocator_deserialize blockmerkleroot blocktransactions_deserialize blocktransactionsrequest_deserialize blockundo_deserialize bloomfilter_deserialize coins_deserialize diskblockindex_deserialize fee_rate_deserialize flat_file_pos_deserialize inv_deserialize key_origin_info_deserialize merkle_block_deserialize messageheader_deserialize netaddr_deserialize out_point_deserialize partial_merkle_tree_deserialize partially_signed_transaction_deserialize prefilled_transaction_deserialize psbt_input_deserialize psbt_output_deserialize pub_key_deserialize script_deserialize service_deserialize snapshotmetadata_deserialize sub_net_deserialize tx_in_deserialize txoutcompressor_deserialize txundo_deserialize uint160_deserialize uint256_deserialize ) add_process_message_fuzz_targets( addr block blocktxn cmpctblock feefilter filteradd filterclear filterload getaddr getblocks getblocktxn getdata getheaders headers inv mempool notfound ping pong sendcmpct sendheaders tx verack version ) diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp new file mode 100644 index 000000000..56f1e6381 --- /dev/null +++ b/src/test/fuzz/banman.cpp @@ -0,0 +1,95 @@ +// 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 + +namespace { +int64_t +ConsumeBanTimeOffset(FuzzedDataProvider &fuzzed_data_provider) noexcept { + // Avoid signed integer overflow by capping to int32_t max: + // banman.cpp:137:73: runtime error: signed integer overflow: 1591700817 + + // 9223372036854775807 cannot be represented in type 'long' + return fuzzed_data_provider.ConsumeIntegralInRange( + std::numeric_limits::min(), + std::numeric_limits::max()); +} +} // namespace + +void initialize() { + InitializeFuzzingContext(); +} + +void test_one_input(const std::vector &buffer) { + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + const fs::path banlist_file = GetDataDir() / "fuzzed_banlist.dat"; + fs::remove(banlist_file); + const CChainParams &chainparams = GetConfig().GetChainParams(); + { + BanMan ban_man{banlist_file, chainparams, nullptr, + ConsumeBanTimeOffset(fuzzed_data_provider)}; + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 11)) { + case 0: { + ban_man.Ban(ConsumeNetAddr(fuzzed_data_provider), + ConsumeBanTimeOffset(fuzzed_data_provider), + fuzzed_data_provider.ConsumeBool()); + break; + } + case 1: { + ban_man.Ban(ConsumeSubNet(fuzzed_data_provider), + ConsumeBanTimeOffset(fuzzed_data_provider), + fuzzed_data_provider.ConsumeBool()); + break; + } + case 2: { + ban_man.ClearBanned(); + break; + } + case 4: { + ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider)); + break; + } + case 5: { + ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider)); + break; + } + case 6: { + ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider)); + break; + } + case 7: { + ban_man.Unban(ConsumeSubNet(fuzzed_data_provider)); + break; + } + case 8: { + banmap_t banmap; + ban_man.GetBanned(banmap); + break; + } + case 9: { + ban_man.DumpBanlist(); + break; + } + case 11: { + ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider)); + break; + } + } + } + } + fs::remove(banlist_file); +} diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp index e5ed3df7a..a4cb3b887 100644 --- a/src/test/fuzz/netaddress.cpp +++ b/src/test/fuzz/netaddress.cpp @@ -1,148 +1,117 @@ // 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 -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); const CService other_service{ net_addr, fuzzed_data_provider.ConsumeIntegral()}; assert((service == other_service) != (service != other_service)); (void)(service < other_service); const CSubNet sub_net_copy_1{net_addr, other_net_addr}; const CSubNet sub_net_copy_2{net_addr}; CNetAddr mutable_net_addr; mutable_net_addr.SetIP(net_addr); assert(net_addr == mutable_net_addr); } diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 0b25b77a4..d8dd7a7a7 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -1,223 +1,262 @@ // Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_TEST_FUZZ_UTIL_H #define BITCOIN_TEST_FUZZ_UTIL_H #include #include #include +#include #include +#include #include