Skip to content

Commit afd237b

Browse files
committed
[fuzz] Harness for version handshake
1 parent a90ab4a commit afd237b

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ test_fuzz_fuzz_SOURCES = \
350350
test/fuzz/netaddress.cpp \
351351
test/fuzz/netbase_dns_lookup.cpp \
352352
test/fuzz/node_eviction.cpp \
353+
test/fuzz/p2p_handshake.cpp \
353354
test/fuzz/p2p_transport_serialization.cpp \
354355
test/fuzz/package_eval.cpp \
355356
test/fuzz/parse_hd_keypath.cpp \

src/test/fuzz/p2p_handshake.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright (c) 2020-present 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 <addrman.h>
6+
#include <consensus/consensus.h>
7+
#include <net.h>
8+
#include <net_processing.h>
9+
#include <node/warnings.h>
10+
#include <protocol.h>
11+
#include <script/script.h>
12+
#include <sync.h>
13+
#include <test/fuzz/FuzzedDataProvider.h>
14+
#include <test/fuzz/fuzz.h>
15+
#include <test/fuzz/util.h>
16+
#include <test/fuzz/util/net.h>
17+
#include <test/util/mining.h>
18+
#include <test/util/net.h>
19+
#include <test/util/setup_common.h>
20+
#include <test/util/validation.h>
21+
#include <util/time.h>
22+
#include <validationinterface.h>
23+
24+
#include <ios>
25+
#include <string>
26+
#include <utility>
27+
#include <vector>
28+
29+
namespace {
30+
const TestingSetup* g_setup;
31+
32+
void initialize()
33+
{
34+
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(
35+
/*chain_type=*/ChainType::REGTEST);
36+
g_setup = testing_setup.get();
37+
}
38+
} // namespace
39+
40+
FUZZ_TARGET(p2p_handshake, .init = ::initialize)
41+
{
42+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
43+
44+
ConnmanTestMsg& connman = static_cast<ConnmanTestMsg&>(*g_setup->m_node.connman);
45+
auto& chainman = static_cast<TestChainstateManager&>(*g_setup->m_node.chainman);
46+
SetMockTime(1610000000); // any time to successfully reset ibd
47+
chainman.ResetIbd();
48+
49+
node::Warnings warnings{};
50+
NetGroupManager netgroupman{{}};
51+
AddrMan addrman{netgroupman, /*deterministic=*/true, 0};
52+
auto peerman = PeerManager::make(connman, addrman,
53+
/*banman=*/nullptr, chainman,
54+
*g_setup->m_node.mempool, warnings,
55+
PeerManager::Options{
56+
.reconcile_txs = true,
57+
.deterministic_rng = true,
58+
});
59+
connman.SetMsgProc(peerman.get());
60+
61+
LOCK(NetEventsInterface::g_msgproc_mutex);
62+
63+
std::vector<CNode*> peers;
64+
const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
65+
for (int i = 0; i < num_peers_to_add; ++i) {
66+
peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, i).release());
67+
connman.AddTestNode(*peers.back());
68+
peerman->InitializeNode(
69+
*peers.back(),
70+
static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()));
71+
}
72+
73+
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100)
74+
{
75+
CNode& connection = *PickValue(fuzzed_data_provider, peers);
76+
if (connection.fDisconnect || connection.fSuccessfullyConnected) {
77+
// Skip if the the connection was disconnected or if the version
78+
// handshake was already completed.
79+
continue;
80+
}
81+
82+
SetMockTime(GetTime() +
83+
fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(
84+
-std::chrono::seconds{10min}.count(), // Allow mocktime to go backwards slightly
85+
std::chrono::seconds{TIMEOUT_INTERVAL}.count()));
86+
87+
CSerializedNetMsg net_msg;
88+
net_msg.m_type = PickValue(fuzzed_data_provider, ALL_NET_MESSAGE_TYPES);
89+
net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider, MAX_PROTOCOL_MESSAGE_LENGTH);
90+
91+
connman.FlushSendBuffer(connection);
92+
(void)connman.ReceiveMsgFrom(connection, std::move(net_msg));
93+
94+
bool more_work{true};
95+
while (more_work) {
96+
connection.fPauseSend = false;
97+
98+
try {
99+
more_work = connman.ProcessMessagesOnce(connection);
100+
} catch (const std::ios_base::failure&) {
101+
}
102+
peerman->SendMessages(&connection);
103+
}
104+
}
105+
106+
g_setup->m_node.connman->StopNodes();
107+
}

src/test/util/net.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class Span;
3434
struct ConnmanTestMsg : public CConnman {
3535
using CConnman::CConnman;
3636

37+
void SetMsgProc(NetEventsInterface* msgproc)
38+
{
39+
m_msgproc = msgproc;
40+
}
41+
3742
void SetPeerConnectTimeout(std::chrono::seconds timeout)
3843
{
3944
m_peer_connect_timeout = timeout;

0 commit comments

Comments
 (0)