Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115446
D8005.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Subscribers
None
D8005.diff
View Options
diff --git a/src/net_processing.h b/src/net_processing.h
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -128,4 +128,9 @@
/** Relay transaction to every node */
void RelayTransaction(const TxId &txid, const CConnman &connman);
+bool ProcessMessage(const Config &config, CNode *pfrom,
+ const std::string &strCommand, CDataStream &vRecv,
+ int64_t nTimeReceived, CConnman *connman, BanMan *banman,
+ const std::atomic<bool> &interruptMsgProc);
+
#endif // BITCOIN_NET_PROCESSING_H
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -2230,11 +2230,10 @@
}
}
-static bool ProcessMessage(const Config &config, CNode *pfrom,
- const std::string &strCommand, CDataStream &vRecv,
- int64_t nTimeReceived, CConnman *connman,
- BanMan *banman,
- const std::atomic<bool> &interruptMsgProc) {
+bool ProcessMessage(const Config &config, CNode *pfrom,
+ const std::string &strCommand, CDataStream &vRecv,
+ int64_t nTimeReceived, CConnman *connman, BanMan *banman,
+ const std::atomic<bool> &interruptMsgProc) {
const CChainParams &chainparams = config.GetChainParams();
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n",
SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt
--- a/src/test/fuzz/CMakeLists.txt
+++ b/src/test/fuzz/CMakeLists.txt
@@ -44,6 +44,21 @@
endforeach()
endfunction()
+function(add_process_message_fuzz_targets)
+ foreach(_fuzz_test_name ${ARGN})
+ sanitize_target_name("fuzz-process_message_" ${_fuzz_test_name} _fuzz_target_name)
+ add_fuzz_target(
+ ${_fuzz_target_name}
+ process_message_${_fuzz_test_name}
+
+ # Sources
+ process_message.cpp
+ )
+
+ target_compile_definitions(${_fuzz_target_name} PRIVATE MESSAGE_TYPE=${_fuzz_test_name})
+ endforeach()
+endfunction()
+
add_regular_fuzz_targets(
addrdb
bloom_filter
@@ -53,6 +68,7 @@
eval_script
net_permissions
parse_iso8601
+ process_message
psbt
script
script_flags
@@ -101,3 +117,30 @@
txoutcompressor_deserialize
txundo_deserialize
)
+
+add_process_message_fuzz_targets(
+ addr
+ block
+ blocktxn
+ cmpctblock
+ feefilter
+ filteradd
+ filterclear
+ filterload
+ getaddr
+ getblocks
+ getblocktxn
+ getdata
+ getheaders
+ headers
+ inv
+ mempool
+ notfound
+ ping
+ pong
+ sendcmpct
+ sendheaders
+ tx
+ verack
+ version
+)
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
new file mode 100644
--- /dev/null
+++ b/src/test/fuzz/process_message.cpp
@@ -0,0 +1,129 @@
+// 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 <banman.h>
+#include <chainparams.h>
+#include <config.h>
+#include <consensus/consensus.h>
+#include <net.h>
+#include <net_processing.h>
+#include <protocol.h>
+#include <scheduler.h>
+#include <script/script.h>
+#include <streams.h>
+#include <validationinterface.h>
+#include <version.h>
+
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/util/mining.h>
+#include <test/util/setup_common.h>
+
+#include <algorithm>
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <cstdint>
+#include <iosfwd>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+namespace {
+
+#ifdef MESSAGE_TYPE
+#define TO_STRING_(s) #s
+#define TO_STRING(s) TO_STRING_(s)
+const std::string LIMIT_TO_MESSAGE_TYPE{TO_STRING(MESSAGE_TYPE)};
+#else
+const std::string LIMIT_TO_MESSAGE_TYPE;
+#endif
+
+const std::map<std::string, std::set<std::string>>
+ EXPECTED_DESERIALIZATION_EXCEPTIONS = {
+ {"CDataStream::read(): end of data: iostream error",
+ {"addr", "block", "blocktxn", "cmpctblock", "feefilter", "filteradd",
+ "filterload", "getblocks", "getblocktxn", "getdata", "getheaders",
+ "headers", "inv", "notfound", "ping", "sendcmpct", "tx"}},
+ {"CompactSize exceeds limit of type: iostream error", {"cmpctblock"}},
+ {"differential value overflow: iostream error", {"getblocktxn"}},
+ {"index overflowed 16 bits: iostream error", {"getblocktxn"}},
+ {"index overflowed 16-bits: iostream error", {"cmpctblock"}},
+ {"indexes overflowed 16 bits: iostream error", {"getblocktxn"}},
+ {"non-canonical ReadCompactSize(): iostream error",
+ {"addr", "block", "blocktxn", "cmpctblock", "filteradd", "filterload",
+ "getblocks", "getblocktxn", "getdata", "getheaders", "headers", "inv",
+ "notfound", "tx"}},
+ {"ReadCompactSize(): size too large: iostream error",
+ {"addr", "block", "blocktxn", "cmpctblock", "filteradd", "filterload",
+ "getblocks", "getblocktxn", "getdata", "getheaders", "headers", "inv",
+ "notfound", "tx"}},
+ {"Superfluous witness record: iostream error",
+ {"block", "blocktxn", "cmpctblock", "tx"}},
+ {"Unknown transaction optional data: iostream error",
+ {"block", "blocktxn", "cmpctblock", "tx"}},
+};
+
+const RegTestingSetup *g_setup;
+} // namespace
+
+void initialize() {
+ static RegTestingSetup setup{};
+ g_setup = &setup;
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
+ MineBlock(GetConfig(), g_setup->m_node, CScript() << OP_TRUE);
+ }
+ SyncWithValidationInterfaceQueue();
+}
+
+void test_one_input(const std::vector<uint8_t> &buffer) {
+ const Config &config = GetConfig();
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const std::string random_message_type{
+ fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE)
+ .c_str()};
+ if (!LIMIT_TO_MESSAGE_TYPE.empty() &&
+ random_message_type != LIMIT_TO_MESSAGE_TYPE) {
+ return;
+ }
+ CDataStream random_bytes_data_stream{
+ fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>(), SER_NETWORK,
+ PROTOCOL_VERSION};
+ CNode p2p_node{0,
+ ServiceFlags(NODE_NETWORK | NODE_BLOOM),
+ 0,
+ INVALID_SOCKET,
+ CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK},
+ 0,
+ 0,
+ CAddress{},
+ std::string{},
+ false};
+ p2p_node.fSuccessfullyConnected = true;
+ p2p_node.nVersion = PROTOCOL_VERSION;
+ p2p_node.SetSendVersion(PROTOCOL_VERSION);
+ g_setup->m_node.peer_logic->InitializeNode(config, &p2p_node);
+ try {
+ (void)ProcessMessage(
+ config, &p2p_node, random_message_type, random_bytes_data_stream,
+ GetTimeMillis(), g_setup->m_node.connman.get(),
+ g_setup->m_node.banman.get(), std::atomic<bool>{false});
+ } catch (const std::ios_base::failure &e) {
+ const std::string exception_message{e.what()};
+ const auto p =
+ EXPECTED_DESERIALIZATION_EXCEPTIONS.find(exception_message);
+ if (p == EXPECTED_DESERIALIZATION_EXCEPTIONS.cend() ||
+ p->second.count(random_message_type) == 0) {
+ std::cout << "Unexpected exception when processing message type \""
+ << random_message_type << "\": " << exception_message
+ << std::endl;
+ assert(false);
+ }
+ }
+ SyncWithValidationInterfaceQueue();
+}
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -15,6 +15,7 @@
#include <logging.h>
#include <miner.h>
#include <net.h>
+#include <net_processing.h>
#include <noui.h>
#include <pow/pow.h>
#include <rpc/blockchain.h>
@@ -85,7 +86,7 @@
BasicTestingSetup::BasicTestingSetup(const std::string &chainName)
: m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME /
- std::to_string(g_insecure_rand_ctx_temp_path.rand32())} {
+ g_insecure_rand_ctx_temp_path.rand256().ToString()} {
SetMockTime(0);
fs::create_directories(m_path_root);
gArgs.ForceSetArg("-datadir", m_path_root.string());
@@ -176,6 +177,8 @@
nullptr, DEFAULT_MISBEHAVING_BANTIME);
// Deterministic randomness for tests.
m_node.connman = std::make_unique<CConnman>(config, 0x1337, 0x1337);
+ m_node.peer_logic = std::make_unique<PeerLogicValidation>(
+ m_node.connman.get(), m_node.banman.get(), *m_node.scheduler);
}
TestingSetup::~TestingSetup() {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 1, 11:06 (14 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187502
Default Alt Text
D8005.diff (8 KB)
Attached To
D8005: tests: Add fuzzing harness for ProcessMessage(...). Enables high-level fuzzing of the P2P layer.
Event Timeline
Log In to Comment