Page MenuHomePhabricator

D8005.diff
No OneTemporary

D8005.diff

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

Mime Type
text/plain
Expires
Sat, Mar 1, 11:06 (19 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187502
Default Alt Text
D8005.diff (8 KB)

Event Timeline