aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2020-04-09 00:14:23 +0800
committerMarcoFalke <falke.marco@gmail.com>2020-04-09 00:14:31 +0800
commit3410fe688739f9fc7545043d052dd77fb35de573 (patch)
tree649337388ff67ec05a4475f9febbf0284be942a5
parent4c5923637653a4eeb4d2b13281ce7f4c021fda64 (diff)
parentfa6a00843447d53a5708ea3a629b9150cfe58be2 (diff)
Merge #18521: fuzz: Add process_messages harness
fa6a00843447d53a5708ea3a629b9150cfe58be2 fuzz: Add process_messages harness (MarcoFalke) Pull request description: ACKs for top commit: practicalswift: Tested ACK fa6a00843447d53a5708ea3a629b9150cfe58be2 Tree-SHA512: 2d8788308c7f45c97ca003378f58a9d51f51265958557a65e5e505b1666b4cb928f0d010622870175090a0ad25e2d10b41f26f4eef14b6ff334a024baa250f8c
-rw-r--r--src/Makefile.test.include7
-rw-r--r--src/Makefile.test_util.include2
-rw-r--r--src/net.h3
-rw-r--r--src/test/fuzz/process_messages.cpp75
-rw-r--r--src/test/util/net.cpp39
-rw-r--r--src/test/util/net.h33
-rw-r--r--src/test/util/setup_common.cpp5
7 files changed, 164 insertions, 0 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index e775ae43a1..d5c19f33d2 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -66,6 +66,7 @@ FUZZ_TARGETS = \
test/fuzz/partially_signed_transaction_deserialize \
test/fuzz/pow \
test/fuzz/prefilled_transaction_deserialize \
+ test/fuzz/process_messages \
test/fuzz/process_message \
test/fuzz/process_message_addr \
test/fuzz/process_message_block \
@@ -662,6 +663,12 @@ test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_prefilled_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
+test_fuzz_process_messages_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_process_messages_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_process_messages_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_process_messages_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_messages_SOURCES = test/fuzz/process_messages.cpp
+
test_fuzz_process_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_process_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index 505d630b7d..d7bc73defb 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -11,6 +11,7 @@ TEST_UTIL_H = \
test/util/blockfilter.h \
test/util/logging.h \
test/util/mining.h \
+ test/util/net.h \
test/util/setup_common.h \
test/util/str.h \
test/util/transaction_utils.h \
@@ -22,6 +23,7 @@ libtest_util_a_SOURCES = \
test/util/blockfilter.cpp \
test/util/logging.cpp \
test/util/mining.cpp \
+ test/util/net.cpp \
test/util/setup_common.cpp \
test/util/str.cpp \
test/util/transaction_utils.cpp \
diff --git a/src/net.h b/src/net.h
index 96ac33b536..a72af83eef 100644
--- a/src/net.h
+++ b/src/net.h
@@ -479,6 +479,7 @@ private:
std::atomic<int64_t> m_next_send_inv_to_incoming{0};
friend struct CConnmanTest;
+ friend struct ConnmanTestMsg;
};
void Discover();
void StartMapPort();
@@ -718,6 +719,8 @@ public:
class CNode
{
friend class CConnman;
+ friend struct ConnmanTestMsg;
+
public:
std::unique_ptr<TransportDeserializer> m_deserializer;
std::unique_ptr<TransportSerializer> m_serializer;
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
new file mode 100644
index 0000000000..12a5dbb607
--- /dev/null
+++ b/src/test/fuzz/process_messages.cpp
@@ -0,0 +1,75 @@
+// 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 <consensus/consensus.h>
+#include <net.h>
+#include <net_processing.h>
+#include <protocol.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/mining.h>
+#include <test/util/net.h>
+#include <test/util/setup_common.h>
+#include <util/memory.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+const RegTestingSetup* g_setup;
+
+void initialize()
+{
+ static RegTestingSetup setup{};
+ g_setup = &setup;
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
+ MineBlock(g_setup->m_node, CScript() << OP_TRUE);
+ }
+ SyncWithValidationInterfaceQueue();
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
+ std::vector<CNode*> peers;
+
+ const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
+ for (int i = 0; i < num_peers_to_add; ++i) {
+ const ServiceFlags service_flags = ServiceFlags(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ const bool inbound{fuzzed_data_provider.ConsumeBool()};
+ const bool block_relay_only{fuzzed_data_provider.ConsumeBool()};
+ 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());
+ CNode& p2p_node = *peers.back();
+
+ p2p_node.fSuccessfullyConnected = true;
+ p2p_node.fPauseSend = false;
+ p2p_node.nVersion = PROTOCOL_VERSION;
+ p2p_node.SetSendVersion(PROTOCOL_VERSION);
+ g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
+
+ connman.AddTestNode(p2p_node);
+ }
+
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()};
+
+ CSerializedNetMsg net_msg;
+ net_msg.command = random_message_type;
+ net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+
+ CNode& random_node = *peers.at(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, peers.size() - 1));
+
+ (void)connman.ReceiveMsgFrom(random_node, net_msg);
+ random_node.fPauseSend = false;
+
+ try {
+ connman.ProcessMessagesOnce(random_node);
+ } catch (const std::ios_base::failure&) {
+ }
+ }
+ connman.ClearTestNodes();
+ SyncWithValidationInterfaceQueue();
+}
diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp
new file mode 100644
index 0000000000..09f2f1807f
--- /dev/null
+++ b/src/test/util/net.cpp
@@ -0,0 +1,39 @@
+// 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 <test/util/net.h>
+
+#include <chainparams.h>
+#include <net.h>
+
+void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const
+{
+ assert(node.ReceiveMsgBytes(pch, nBytes, complete));
+ if (complete) {
+ size_t nSizeAdded = 0;
+ auto it(node.vRecvMsg.begin());
+ for (; it != node.vRecvMsg.end(); ++it) {
+ // vRecvMsg contains only completed CNetMessage
+ // the single possible partially deserialized message are held by TransportDeserializer
+ nSizeAdded += it->m_raw_message_size;
+ }
+ {
+ LOCK(node.cs_vProcessMsg);
+ node.vProcessMsg.splice(node.vProcessMsg.end(), node.vRecvMsg, node.vRecvMsg.begin(), it);
+ node.nProcessQueueSize += nSizeAdded;
+ node.fPauseRecv = node.nProcessQueueSize > nReceiveFloodSize;
+ }
+ }
+}
+
+bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const
+{
+ std::vector<unsigned char> ser_msg_header;
+ node.m_serializer->prepareForTransport(ser_msg, ser_msg_header);
+
+ bool complete;
+ NodeReceiveMsgBytes(node, (const char*)ser_msg_header.data(), ser_msg_header.size(), complete);
+ NodeReceiveMsgBytes(node, (const char*)ser_msg.data.data(), ser_msg.data.size(), complete);
+ return complete;
+}
diff --git a/src/test/util/net.h b/src/test/util/net.h
new file mode 100644
index 0000000000..ca8cb7fad5
--- /dev/null
+++ b/src/test/util/net.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef BITCOIN_TEST_UTIL_NET_H
+#define BITCOIN_TEST_UTIL_NET_H
+
+#include <net.h>
+
+struct ConnmanTestMsg : public CConnman {
+ using CConnman::CConnman;
+ void AddTestNode(CNode& node)
+ {
+ LOCK(cs_vNodes);
+ vNodes.push_back(&node);
+ }
+ void ClearTestNodes()
+ {
+ LOCK(cs_vNodes);
+ for (CNode* node : vNodes) {
+ delete node;
+ }
+ vNodes.clear();
+ }
+
+ void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); }
+
+ void NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const;
+
+ bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const;
+};
+
+#endif // BITCOIN_TEST_UTIL_NET_H
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index d684b97787..a4d0126925 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -139,6 +139,11 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
m_node.peer_logic = MakeUnique<PeerLogicValidation>(m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.mempool);
+ {
+ CConnman::Options options;
+ options.m_msgproc = m_node.peer_logic.get();
+ m_node.connman->Init(options);
+ }
}
TestingSetup::~TestingSetup()