Skip to content

Commit fa6a008

Browse files
author
MarcoFalke
committed
fuzz: Add process_messages harness
1 parent 96a30b9 commit fa6a008

File tree

7 files changed

+164
-0
lines changed

7 files changed

+164
-0
lines changed

src/Makefile.test.include

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ FUZZ_TARGETS = \
6262
test/fuzz/partially_signed_transaction_deserialize \
6363
test/fuzz/pow \
6464
test/fuzz/prefilled_transaction_deserialize \
65+
test/fuzz/process_messages \
6566
test/fuzz/process_message \
6667
test/fuzz/process_message_addr \
6768
test/fuzz/process_message_block \
@@ -642,6 +643,12 @@ test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
642643
test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
643644
test_fuzz_prefilled_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
644645

646+
test_fuzz_process_messages_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
647+
test_fuzz_process_messages_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
648+
test_fuzz_process_messages_LDADD = $(FUZZ_SUITE_LD_COMMON)
649+
test_fuzz_process_messages_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
650+
test_fuzz_process_messages_SOURCES = test/fuzz/process_messages.cpp
651+
645652
test_fuzz_process_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
646653
test_fuzz_process_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
647654
test_fuzz_process_message_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/Makefile.test_util.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ TEST_UTIL_H = \
1111
test/util/blockfilter.h \
1212
test/util/logging.h \
1313
test/util/mining.h \
14+
test/util/net.h \
1415
test/util/setup_common.h \
1516
test/util/str.h \
1617
test/util/transaction_utils.h \
@@ -22,6 +23,7 @@ libtest_util_a_SOURCES = \
2223
test/util/blockfilter.cpp \
2324
test/util/logging.cpp \
2425
test/util/mining.cpp \
26+
test/util/net.cpp \
2527
test/util/setup_common.cpp \
2628
test/util/str.cpp \
2729
test/util/transaction_utils.cpp \

src/net.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ class CConnman
482482
std::atomic<int64_t> m_next_send_inv_to_incoming{0};
483483

484484
friend struct CConnmanTest;
485+
friend struct ConnmanTestMsg;
485486
};
486487
void Discover();
487488
void StartMapPort();
@@ -721,6 +722,8 @@ class V1TransportSerializer : public TransportSerializer {
721722
class CNode
722723
{
723724
friend class CConnman;
725+
friend struct ConnmanTestMsg;
726+
724727
public:
725728
std::unique_ptr<TransportDeserializer> m_deserializer;
726729
std::unique_ptr<TransportSerializer> m_serializer;

src/test/fuzz/process_messages.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) 2020 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 <protocol.h>
9+
#include <test/fuzz/FuzzedDataProvider.h>
10+
#include <test/fuzz/fuzz.h>
11+
#include <test/fuzz/util.h>
12+
#include <test/util/mining.h>
13+
#include <test/util/net.h>
14+
#include <test/util/setup_common.h>
15+
#include <util/memory.h>
16+
#include <validation.h>
17+
#include <validationinterface.h>
18+
19+
const RegTestingSetup* g_setup;
20+
21+
void initialize()
22+
{
23+
static RegTestingSetup setup{};
24+
g_setup = &setup;
25+
26+
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
27+
MineBlock(g_setup->m_node, CScript() << OP_TRUE);
28+
}
29+
SyncWithValidationInterfaceQueue();
30+
}
31+
32+
void test_one_input(const std::vector<uint8_t>& buffer)
33+
{
34+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
35+
36+
ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
37+
std::vector<CNode*> peers;
38+
39+
const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
40+
for (int i = 0; i < num_peers_to_add; ++i) {
41+
const ServiceFlags service_flags = ServiceFlags(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
42+
const bool inbound{fuzzed_data_provider.ConsumeBool()};
43+
const bool block_relay_only{fuzzed_data_provider.ConsumeBool()};
44+
peers.push_back(MakeUnique<CNode>(i, service_flags, 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, inbound, block_relay_only).release());
45+
CNode& p2p_node = *peers.back();
46+
47+
p2p_node.fSuccessfullyConnected = true;
48+
p2p_node.fPauseSend = false;
49+
p2p_node.nVersion = PROTOCOL_VERSION;
50+
p2p_node.SetSendVersion(PROTOCOL_VERSION);
51+
g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
52+
53+
connman.AddTestNode(p2p_node);
54+
}
55+
56+
while (fuzzed_data_provider.ConsumeBool()) {
57+
const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()};
58+
59+
CSerializedNetMsg net_msg;
60+
net_msg.command = random_message_type;
61+
net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
62+
63+
CNode& random_node = *peers.at(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, peers.size() - 1));
64+
65+
(void)connman.ReceiveMsgFrom(random_node, net_msg);
66+
random_node.fPauseSend = false;
67+
68+
try {
69+
connman.ProcessMessagesOnce(random_node);
70+
} catch (const std::ios_base::failure&) {
71+
}
72+
}
73+
connman.ClearTestNodes();
74+
SyncWithValidationInterfaceQueue();
75+
}

src/test/util/net.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2020 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 <test/util/net.h>
6+
7+
#include <chainparams.h>
8+
#include <net.h>
9+
10+
void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const
11+
{
12+
assert(node.ReceiveMsgBytes(pch, nBytes, complete));
13+
if (complete) {
14+
size_t nSizeAdded = 0;
15+
auto it(node.vRecvMsg.begin());
16+
for (; it != node.vRecvMsg.end(); ++it) {
17+
// vRecvMsg contains only completed CNetMessage
18+
// the single possible partially deserialized message are held by TransportDeserializer
19+
nSizeAdded += it->m_raw_message_size;
20+
}
21+
{
22+
LOCK(node.cs_vProcessMsg);
23+
node.vProcessMsg.splice(node.vProcessMsg.end(), node.vRecvMsg, node.vRecvMsg.begin(), it);
24+
node.nProcessQueueSize += nSizeAdded;
25+
node.fPauseRecv = node.nProcessQueueSize > nReceiveFloodSize;
26+
}
27+
}
28+
}
29+
30+
bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const
31+
{
32+
std::vector<unsigned char> ser_msg_header;
33+
node.m_serializer->prepareForTransport(ser_msg, ser_msg_header);
34+
35+
bool complete;
36+
NodeReceiveMsgBytes(node, (const char*)ser_msg_header.data(), ser_msg_header.size(), complete);
37+
NodeReceiveMsgBytes(node, (const char*)ser_msg.data.data(), ser_msg.data.size(), complete);
38+
return complete;
39+
}

src/test/util/net.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2020 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+
#ifndef BITCOIN_TEST_UTIL_NET_H
6+
#define BITCOIN_TEST_UTIL_NET_H
7+
8+
#include <net.h>
9+
10+
struct ConnmanTestMsg : public CConnman {
11+
using CConnman::CConnman;
12+
void AddTestNode(CNode& node)
13+
{
14+
LOCK(cs_vNodes);
15+
vNodes.push_back(&node);
16+
}
17+
void ClearTestNodes()
18+
{
19+
LOCK(cs_vNodes);
20+
for (CNode* node : vNodes) {
21+
delete node;
22+
}
23+
vNodes.clear();
24+
}
25+
26+
void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); }
27+
28+
void NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const;
29+
30+
bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const;
31+
};
32+
33+
#endif // BITCOIN_TEST_UTIL_NET_H

src/test/util/setup_common.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
139139
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
140140
m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
141141
m_node.peer_logic = MakeUnique<PeerLogicValidation>(m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.mempool);
142+
{
143+
CConnman::Options options;
144+
options.m_msgproc = m_node.peer_logic.get();
145+
m_node.connman->Init(options);
146+
}
142147
}
143148

144149
TestingSetup::~TestingSetup()

0 commit comments

Comments
 (0)