Branch data Line data Source code
1 : : // Copyright (c) 2020-2022 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 <consensus/consensus.h> 6 : : #include <net.h> 7 : : #include <net_processing.h> 8 : : #include <node/connection_types.h> 9 : : #include <primitives/transaction.h> 10 : : #include <protocol.h> 11 : : #include <script/script.h> 12 : : #include <test/fuzz/FuzzedDataProvider.h> 13 : : #include <test/fuzz/fuzz.h> 14 : : #include <test/fuzz/util.h> 15 : : #include <test/util/mining.h> 16 : : #include <test/util/setup_common.h> 17 [ + - ]: 2 : #include <test/util/validation.h> 18 [ + - ]: 2 : #include <util/chaintype.h> 19 : : #include <util/check.h> 20 : : #include <util/time.h> 21 : : #include <validationinterface.h> 22 : : 23 : : #include <algorithm> 24 : : #include <cstdlib> 25 : : #include <memory> 26 : : #include <optional> 27 : : #include <stdint.h> 28 : : #include <string.h> 29 : : #include <string> 30 : : #include <string_view> 31 : : #include <vector> 32 : : 33 : : // There are two sets of tests: 34 : : // - direct: pass the fuzzed message directly to PeerManager::ProcessMessage() (fuzz/process_message.cpp) 35 : : // - e2e: send the fuzzed message to a mocked socket which is read from Connman 36 : : // and processed by PeerManager (like it is happening in the "real world") (fuzz/process_message_e2e.cpp) 37 : : 38 : : namespace { 39 : : NetTestingSetup* g_setup; 40 : : std::string_view LIMIT_TO_MESSAGE_TYPE{}; 41 : : } // namespace 42 : : 43 : 1 : void initialize_process_message_e2e() 44 : : { 45 [ + - ]: 1 : if (const auto val{std::getenv("LIMIT_TO_MESSAGE_TYPE")}) { 46 : 0 : LIMIT_TO_MESSAGE_TYPE = val; 47 : 0 : Assert(std::count(getAllNetMessageTypes().begin(), getAllNetMessageTypes().end(), LIMIT_TO_MESSAGE_TYPE)); // Unknown message type passed 48 : 0 : } 49 : : 50 [ + - ][ - + ]: 2 : static const auto testing_setup = MakeNoLogFileContext<NetTestingSetup>( [ - + ] 51 : : /*chain_type=*/ChainType::REGTEST, 52 [ + - ]: 1 : /*extra_args=*/{"-txreconciliation"}); 53 : 1 : g_setup = testing_setup.get(); 54 [ + + ]: 201 : for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) { 55 [ + - ][ + - ]: 200 : MineBlock(g_setup->m_node, CScript() << OP_TRUE); 56 : 200 : } 57 : 1 : SyncWithValidationInterfaceQueue(); 58 : 1 : } 59 : : 60 [ + - ]: 148 : FUZZ_TARGET(process_message_e2e, .init = initialize_process_message_e2e) 61 : : { 62 : 144 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 63 : : 64 [ + - ]: 144 : const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; 65 [ - + ][ # # ]: 144 : if (!LIMIT_TO_MESSAGE_TYPE.empty() && random_message_type != LIMIT_TO_MESSAGE_TYPE) { 66 : 0 : return; 67 : : } 68 : : 69 : : // Enter IBD. Since the chain tip is from 2011, set the mock time so that the chain tip 70 : : // is 24h or older. 1610000000 is from 2021. 71 [ + - ]: 144 : SetMockTime(1610000000); 72 [ + - ]: 144 : static_cast<TestChainstateManager&>(*g_setup->m_node.chainman).ResetIbd(); 73 : : 74 [ + - ][ + - ]: 144 : g_setup->m_node.connman->OpenNetworkConnection(/*addrConnect=*/CAddress{}, 75 : : /*fCountFailure=*/false, 76 : 144 : /*grant_outbound=*/CSemaphoreGrant{}, 77 : : /*strDest=*/"1.2.3.4:8333", 78 : : /*conn_type=*/ConnectionType::OUTBOUND_FULL_RELAY, 79 : : /*use_v2transport=*/false); 80 : : 81 [ + - ]: 144 : const auto pipes{g_setup->m_sockets_pipes.PopFront()}; 82 : : 83 [ + - ]: 2 : uint8_t buf[1024]; 84 : : 85 [ + - ][ + + ]: 5533 : LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 100) { [ + + ] 86 : : 87 [ + - ]: 5391 : pipes->recv.PushNetMsg(random_message_type, ConsumeRandomLengthByteVector(fuzzed_data_provider)); 88 : : 89 [ + - ][ + + ]: 5391 : if (pipes->send.GetBytes(buf, sizeof(buf)) == 0) { // EOF, the socket has been closed. 90 : 2 : return; 91 : : } 92 : : 93 : : // Will jump out of IBD if it happens to be before the chain tip (2011). 94 : 5389 : const auto mock_time = ConsumeTime(fuzzed_data_provider); 95 [ + - ]: 5389 : SetMockTime(mock_time); 96 : 5389 : } 97 : : 98 : : // Force a disconnect and wait for it. 99 [ + - ]: 143 : g_setup->m_node.connman->ForEachNode([&](CNode* node) { 100 : 1 : g_setup->m_node.peerman->UnitTestMisbehaving(node->GetId(), DISCOURAGEMENT_THRESHOLD); 101 : 1 : }); 102 : 142 : memset(buf, 0x0, sizeof(buf)); 103 [ + - ]: 142 : pipes->recv.PushBytes(buf, sizeof(buf)); 104 [ + - ][ + + ]: 206 : while (pipes->send.GetNetMsg().has_value()) { 105 : : ; 106 : : } 107 : : 108 [ + - ]: 142 : SyncWithValidationInterfaceQueue(); 109 [ - + ]: 144 : }