diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 7fac78f973b..157b62cef5f 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -35,6 +35,7 @@ FUZZ_TARGETS = \ test/fuzz/checkqueue \ test/fuzz/coins_deserialize \ test/fuzz/coins_view \ + test/fuzz/connman \ test/fuzz/crypto \ test/fuzz/crypto_aes256 \ test/fuzz/crypto_aes256cbc \ @@ -520,6 +521,12 @@ test_fuzz_coins_view_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_coins_view_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) test_fuzz_coins_view_SOURCES = test/fuzz/coins_view.cpp +test_fuzz_connman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_connman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_connman_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_connman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON) +test_fuzz_connman_SOURCES = test/fuzz/connman.cpp + test_fuzz_crypto_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_fuzz_crypto_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_crypto_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp new file mode 100644 index 00000000000..bb9d28a4abe --- /dev/null +++ b/src/test/fuzz/connman.cpp @@ -0,0 +1,162 @@ +// 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 + +void initialize() +{ + InitializeFuzzingContext(); +} + +void test_one_input(const std::vector& buffer) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + CConnman connman{fuzzed_data_provider.ConsumeIntegral(), fuzzed_data_provider.ConsumeIntegral(), fuzzed_data_provider.ConsumeBool()}; + CAddress random_address; + CNetAddr random_netaddr; + CNode random_node = ConsumeNode(fuzzed_data_provider); + CService random_service; + CSubNet random_subnet; + std::string random_string; + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 30)) { + case 0: + random_address = ConsumeAddress(fuzzed_data_provider); + break; + case 1: + random_netaddr = ConsumeNetAddr(fuzzed_data_provider); + break; + case 2: + random_service = ConsumeService(fuzzed_data_provider); + break; + case 3: + random_subnet = ConsumeSubNet(fuzzed_data_provider); + break; + case 4: + random_string = fuzzed_data_provider.ConsumeRandomLengthString(64); + break; + case 5: { + std::vector addresses; + while (fuzzed_data_provider.ConsumeBool()) { + addresses.push_back(ConsumeAddress(fuzzed_data_provider)); + } + // Limit nTimePenalty to int32_t to avoid signed integer overflow + (void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral()); + break; + } + case 6: + connman.AddNode(random_string); + break; + case 7: + connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral()); + break; + case 8: + connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral()); + break; + case 9: + connman.DisconnectNode(random_netaddr); + break; + case 10: + connman.DisconnectNode(random_string); + break; + case 11: + connman.DisconnectNode(random_subnet); + break; + case 12: + connman.ForEachNode([](auto) {}); + break; + case 13: + connman.ForEachNodeThen([](auto) {}, []() {}); + break; + case 14: + (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); }); + break; + case 15: + (void)connman.GetAddresses(fuzzed_data_provider.ConsumeIntegral(), fuzzed_data_provider.ConsumeIntegral()); + break; + case 16: { + (void)connman.GetAddresses(random_node, fuzzed_data_provider.ConsumeIntegral(), fuzzed_data_provider.ConsumeIntegral()); + break; + } + case 17: + (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral()); + break; + case 18: + (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN, CConnman::CONNECTIONS_OUT, CConnman::CONNECTIONS_ALL})); + break; + case 19: + connman.MarkAddressGood(random_address); + break; + case 20: + (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool()); + break; + case 21: + // Limit now to int32_t to avoid signed integer overflow + (void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral(), fuzzed_data_provider.ConsumeIntegral()); + break; + case 22: { + CSerializedNetMsg serialized_net_msg; + serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::COMMAND_SIZE); + serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider); + connman.PushMessage(&random_node, std::move(serialized_net_msg)); + break; + } + case 23: + connman.RemoveAddedNode(random_string); + break; + case 24: { + const std::vector asmap = ConsumeRandomLengthIntegralVector(fuzzed_data_provider, 512); + if (SanityCheckASMap(asmap)) { + connman.SetAsmap(asmap); + } + break; + } + case 25: + connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral()); + break; + case 26: + connman.SetMaxOutboundTarget(fuzzed_data_provider.ConsumeIntegral()); + break; + case 27: + connman.SetMaxOutboundTimeframe(fuzzed_data_provider.ConsumeIntegral()); + break; + case 28: + connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); + break; + case 29: + connman.SetServices(random_service, static_cast(fuzzed_data_provider.ConsumeIntegral())); + break; + case 30: + connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool()); + break; + } + } + (void)connman.GetAddedNodeInfo(); + (void)connman.GetBestHeight(); + (void)connman.GetExtraOutboundCount(); + (void)connman.GetLocalServices(); + (void)connman.GetMaxOutboundTarget(); + (void)connman.GetMaxOutboundTimeframe(); + (void)connman.GetMaxOutboundTimeLeftInCycle(); + (void)connman.GetNetworkActive(); + std::vector stats; + connman.GetNodeStats(stats); + (void)connman.GetOutboundTargetBytesLeft(); + (void)connman.GetReceiveFloodSize(); + (void)connman.GetTotalBytesRecv(); + (void)connman.GetTotalBytesSent(); + (void)connman.GetTryNewOutboundPeer(); + (void)connman.GetUseAddrmanOutgoing(); +} diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index ed6093a8a83..fec6e13e863 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,32 @@ CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral()}; } +CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral()}; +} + +CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return {ConsumeService(fuzzed_data_provider), static_cast(fuzzed_data_provider.ConsumeIntegral()), fuzzed_data_provider.ConsumeIntegral()}; +} + +CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + const NodeId node_id = fuzzed_data_provider.ConsumeIntegral(); + const ServiceFlags local_services = static_cast(fuzzed_data_provider.ConsumeIntegral()); + const int my_starting_height = fuzzed_data_provider.ConsumeIntegral(); + const SOCKET socket = INVALID_SOCKET; + const CAddress address = ConsumeAddress(fuzzed_data_provider); + const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral(); + const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral(); + const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider); + const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64); + const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH}); + const bool inbound_onion = fuzzed_data_provider.ConsumeBool(); + return {node_id, local_services, my_starting_height, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion}; +} + void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST) { static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};