Skip to content

Commit 32ab679

Browse files
committed
fuzz: add a test that pushes fuzzed data to the p2p socket
This way the full call chain is being tested/fuzzed, from the socket, to `CConnman`, to `PeerManager` and the interaction between them.
1 parent 5c56f06 commit 32ab679

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ test_fuzz_fuzz_SOURCES = \
288288
test/fuzz/net_permissions.cpp \
289289
test/fuzz/netaddress.cpp \
290290
test/fuzz/netbase_dns_lookup.cpp \
291+
test/fuzz/netmsg.cpp \
291292
test/fuzz/node_eviction.cpp \
292293
test/fuzz/p2p_transport_serialization.cpp \
293294
test/fuzz/parse_hd_keypath.cpp \

src/test/fuzz/netmsg.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright (c) 2020-2023 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 <banman.h>
6+
#include <blockencodings.h>
7+
#include <consensus/consensus.h>
8+
#include <net_processing.h>
9+
#include <protocol.h>
10+
#include <streams.h>
11+
#include <test/fuzz/FuzzedDataProvider.h>
12+
#include <test/fuzz/fuzz.h>
13+
#include <test/fuzz/util.h>
14+
#include <test/util/mining.h>
15+
#include <test/util/setup_common.h>
16+
#include <test/util/validation.h>
17+
#include <util/check.h>
18+
#include <util/time.h>
19+
#include <validationinterface.h>
20+
21+
#include <chrono>
22+
#include <string>
23+
#include <thread>
24+
25+
namespace {
26+
NetTestingSetup* g_setup;
27+
} // namespace
28+
29+
static size_t& GetNumMsgTypes()
30+
{
31+
static size_t g_num_msg_types{0};
32+
return g_num_msg_types;
33+
}
34+
#define FUZZ_TARGET_MSG(msg_type) \
35+
struct msg_type##CountBeforeMain { \
36+
msg_type##CountBeforeMain() \
37+
{ \
38+
++GetNumMsgTypes(); \
39+
} \
40+
} const static g_##msg_type##count_before_main; \
41+
FUZZ_TARGET_INIT(netmsg_##msg_type, initialize_netmsg) \
42+
{ \
43+
fuzz_target(buffer, #msg_type); \
44+
}
45+
46+
void initialize_netmsg()
47+
{
48+
Assert(GetNumMsgTypes() == getAllNetMessageTypes().size()); // If this fails, add or remove the message type below
49+
50+
static const auto testing_setup = MakeNoLogFileContext<NetTestingSetup>();
51+
g_setup = testing_setup.get();
52+
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
53+
MineBlock(g_setup->m_node, CScript() << OP_TRUE);
54+
}
55+
SyncWithValidationInterfaceQueue();
56+
}
57+
58+
static void fuzz_target(FuzzBufferType buffer, const std::string& limit_to_message_type)
59+
{
60+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
61+
62+
SetMockTime(GetMockTime() + std::chrono::minutes{fuzzed_data_provider.ConsumeIntegral<uint8_t>()});
63+
64+
g_setup->m_node.connman->OpenNetworkConnection(
65+
CAddress{}, false, nullptr, "1.2.3.4:8333", ConnectionType::OUTBOUND_FULL_RELAY);
66+
67+
auto pipes = g_setup->m_sockets_pipes.PopFront();
68+
69+
uint8_t buf[1024];
70+
71+
LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 100) {
72+
73+
const std::string message_type =
74+
limit_to_message_type.empty() ?
75+
fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE) :
76+
limit_to_message_type;
77+
78+
CDataStream payload{
79+
ConsumeRandomLengthByteVector(fuzzed_data_provider), SER_NETWORK, PROTOCOL_VERSION};
80+
81+
pipes->recv.PushNetMsg(message_type, payload);
82+
83+
if (pipes->send.GetBytes(buf, sizeof(buf)) == 0) { // EOF, the socket has been closed.
84+
return;
85+
}
86+
}
87+
88+
// Force a disconnect and wait for it.
89+
g_setup->m_node.connman->ForEachNode([&](CNode* node) {
90+
g_setup->m_node.peerman->UnitTestMisbehaving(node->GetId(), DISCOURAGEMENT_THRESHOLD);
91+
});
92+
memset(buf, 0x0, sizeof(buf));
93+
pipes->recv.PushBytes(buf, sizeof(buf));
94+
while (pipes->send.GetNetMsg().has_value()) {
95+
;
96+
}
97+
98+
SyncWithValidationInterfaceQueue();
99+
}
100+
101+
FUZZ_TARGET_INIT(netmsg_any, initialize_netmsg) { fuzz_target(buffer, ""); }
102+
FUZZ_TARGET_MSG(addr);
103+
FUZZ_TARGET_MSG(addrv2);
104+
FUZZ_TARGET_MSG(block);
105+
FUZZ_TARGET_MSG(blocktxn);
106+
FUZZ_TARGET_MSG(cfcheckpt);
107+
FUZZ_TARGET_MSG(cfheaders);
108+
FUZZ_TARGET_MSG(cfilter);
109+
FUZZ_TARGET_MSG(cmpctblock);
110+
FUZZ_TARGET_MSG(feefilter);
111+
FUZZ_TARGET_MSG(filteradd);
112+
FUZZ_TARGET_MSG(filterclear);
113+
FUZZ_TARGET_MSG(filterload);
114+
FUZZ_TARGET_MSG(getaddr);
115+
FUZZ_TARGET_MSG(getblocks);
116+
FUZZ_TARGET_MSG(getblocktxn);
117+
FUZZ_TARGET_MSG(getcfcheckpt);
118+
FUZZ_TARGET_MSG(getcfheaders);
119+
FUZZ_TARGET_MSG(getcfilters);
120+
FUZZ_TARGET_MSG(getdata);
121+
FUZZ_TARGET_MSG(getheaders);
122+
FUZZ_TARGET_MSG(headers);
123+
FUZZ_TARGET_MSG(inv);
124+
FUZZ_TARGET_MSG(mempool);
125+
FUZZ_TARGET_MSG(merkleblock);
126+
FUZZ_TARGET_MSG(notfound);
127+
FUZZ_TARGET_MSG(ping);
128+
FUZZ_TARGET_MSG(pong);
129+
FUZZ_TARGET_MSG(sendaddrv2);
130+
FUZZ_TARGET_MSG(sendcmpct);
131+
FUZZ_TARGET_MSG(sendheaders);
132+
FUZZ_TARGET_MSG(sendtxrcncl);
133+
FUZZ_TARGET_MSG(tx);
134+
FUZZ_TARGET_MSG(verack);
135+
FUZZ_TARGET_MSG(version);
136+
FUZZ_TARGET_MSG(wtxidrelay);

0 commit comments

Comments
 (0)