diff --git a/.gitignore b/.gitignore index 54855b71f771..e5b3265f888a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,7 @@ src/dash-gui src/dash-node src/dash-tx src/dash-wallet -src/test/fuzz/* -!src/test/fuzz/*.* +src/test/fuzz/fuzz src/test/test_dash src/qt/test/test_dash-qt src/qt/res/css/colors/* diff --git a/configure.ac b/configure.ac index ed96c7e0dbb7..1c835b4ff937 100644 --- a/configure.ac +++ b/configure.ac @@ -1960,12 +1960,12 @@ if test x$bitcoin_enable_qt != xno; then fi echo " with zmq = $use_zmq" if test x$enable_fuzz == xno; then - echo " with test = $use_tests" + echo " with test = $use_tests" else - echo " with test = not building test_dash because fuzzing is enabled" - echo " with fuzz = $enable_fuzz" + echo " with test = not building test_dash because fuzzing is enabled" fi -echo " with bench = $use_bench" +echo " with fuzz binary = $enable_fuzz_binary" +echo " with bench = $use_bench" echo " with upnp = $use_upnp" echo " with natpmp = $use_natpmp" echo " use asm = $use_asm" diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 93353dc8ff05..fc1e52d6df74 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -327,6 +327,7 @@ test_fuzz_fuzz_SOURCES = \ test/fuzz/transaction.cpp \ test/fuzz/tx_in.cpp \ test/fuzz/tx_out.cpp \ + test/fuzz/tx_pool.cpp \ test/fuzz/validation_load_mempool.cpp \ test/fuzz/versionbits.cpp endif # ENABLE_FUZZ_BINARY diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include index f55a040bbde0..1a805a1dd1f5 100644 --- a/src/Makefile.test_util.include +++ b/src/Makefile.test_util.include @@ -13,10 +13,12 @@ TEST_UTIL_H = \ test/util/logging.h \ test/util/mining.h \ test/util/net.h \ + test/util/script.h \ test/util/setup_common.h \ test/util/str.h \ test/util/transaction_utils.h \ test/util/wallet.h \ + test/util/validation.h \ test/util/xoroshiro128plusplus.h libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) @@ -27,9 +29,11 @@ libtest_util_a_SOURCES = \ test/util/logging.cpp \ test/util/mining.cpp \ test/util/net.cpp \ + test/util/script.cpp \ test/util/setup_common.cpp \ test/util/str.cpp \ test/util/transaction_utils.cpp \ + test/util/validation.cpp \ test/util/wallet.cpp \ $(TEST_UTIL_H) diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index da96d2fae060..c8f476078022 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -229,11 +230,13 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) // consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, TxValidationState&, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed. return; } - try { - (void)Consensus::CheckTxInputs(transaction, state, coins_view_cache, fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits::max()), tx_fee_out); - assert(MoneyRange(tx_fee_out)); - } catch (const std::runtime_error&) { + TxValidationState dummy; + if (!CheckTransaction(transaction, dummy)) { + // It is not allowed to call CheckTxInputs if CheckTransaction failed + return; } + (void)Consensus::CheckTxInputs(transaction, state, coins_view_cache, fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits::max()), tx_fee_out); + assert(MoneyRange(tx_fee_out)); }, [&] { const CTransaction transaction{random_mutable_transaction}; diff --git a/src/test/fuzz/netbase_dns_lookup.cpp b/src/test/fuzz/netbase_dns_lookup.cpp index 2c984e15ff27..cf2fa337443c 100644 --- a/src/test/fuzz/netbase_dns_lookup.cpp +++ b/src/test/fuzz/netbase_dns_lookup.cpp @@ -12,27 +12,22 @@ #include #include -namespace { -FuzzedDataProvider* fuzzed_data_provider_ptr = nullptr; - -std::vector fuzzed_dns_lookup_function(const std::string& name, bool allow_lookup) -{ - std::vector resolved_addresses; - while (fuzzed_data_provider_ptr->ConsumeBool()) { - resolved_addresses.push_back(ConsumeNetAddr(*fuzzed_data_provider_ptr)); - } - return resolved_addresses; -} -} // namespace - FUZZ_TARGET(netbase_dns_lookup) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; - fuzzed_data_provider_ptr = &fuzzed_data_provider; const std::string name = fuzzed_data_provider.ConsumeRandomLengthString(512); const unsigned int max_results = fuzzed_data_provider.ConsumeIntegral(); const bool allow_lookup = fuzzed_data_provider.ConsumeBool(); const uint16_t default_port = fuzzed_data_provider.ConsumeIntegral(); + + auto fuzzed_dns_lookup_function = [&](const std::string&, bool) { + std::vector resolved_addresses; + while (fuzzed_data_provider.ConsumeBool()) { + resolved_addresses.push_back(ConsumeNetAddr(fuzzed_data_provider)); + } + return resolved_addresses; + }; + { std::vector resolved_addresses; if (LookupHost(name, resolved_addresses, max_results, allow_lookup, fuzzed_dns_lookup_function)) { @@ -73,5 +68,4 @@ FUZZ_TARGET(netbase_dns_lookup) assert(resolved_subnet.IsValid()); } } - fuzzed_data_provider_ptr = nullptr; } diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index fd0ca0644a30..04f51d3fb647 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -35,7 +35,7 @@ FUZZ_TARGET_INIT(pow, initialize_pow) } CBlockIndex current_block{*block_header}; { - CBlockIndex* previous_block = !blocks.empty() ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange(0, blocks.size() - 1)] : nullptr; + CBlockIndex* previous_block = blocks.empty() ? nullptr : &PickValue(fuzzed_data_provider, blocks); const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits::max()) ? previous_block->nHeight + 1 : 0; if (fuzzed_data_provider.ConsumeBool()) { current_block.pprev = previous_block; @@ -64,9 +64,9 @@ FUZZ_TARGET_INIT(pow, initialize_pow) } } { - const CBlockIndex* to = &blocks[fuzzed_data_provider.ConsumeIntegralInRange(0, blocks.size() - 1)]; - const CBlockIndex* from = &blocks[fuzzed_data_provider.ConsumeIntegralInRange(0, blocks.size() - 1)]; - const CBlockIndex* tip = &blocks[fuzzed_data_provider.ConsumeIntegralInRange(0, blocks.size() - 1)]; + const CBlockIndex* to = &PickValue(fuzzed_data_provider, blocks); + const CBlockIndex* from = &PickValue(fuzzed_data_provider, blocks); + const CBlockIndex* tip = &PickValue(fuzzed_data_provider, blocks); try { (void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params); } catch (const uint_error&) { diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 6fe278449bc2..915b949fe400 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -73,7 +74,12 @@ void initialize_process_message() void fuzz_target(FuzzBufferType buffer, const std::string& LIMIT_TO_MESSAGE_TYPE) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get(); + + ConnmanTestMsg& connman = *static_cast(g_setup->m_node.connman.get()); + TestChainState& chainstate = *static_cast(&g_setup->m_node.chainman->ActiveChainstate()); + SetMockTime(1610000000); // any time to successfully reset ibd + chainstate.ResetIbd(); + 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; @@ -86,6 +92,9 @@ void fuzz_target(FuzzBufferType buffer, const std::string& LIMIT_TO_MESSAGE_TYPE g_setup->m_node.peerman->InitializeNode(&p2p_node); FillNode(fuzzed_data_provider, p2p_node, /* init_version */ successfully_connected); + const auto mock_time = ConsumeTime(fuzzed_data_provider); + SetMockTime(mock_time); + // fuzzed_data_provider is fully consumed after this call, don't use it CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes(), SER_NETWORK, PROTOCOL_VERSION}; try { @@ -109,8 +118,16 @@ FUZZ_TARGET_MSG(blocktxn); FUZZ_TARGET_MSG(cfcheckpt); FUZZ_TARGET_MSG(cfheaders); FUZZ_TARGET_MSG(cfilter); +FUZZ_TARGET_MSG(clsig); FUZZ_TARGET_MSG(cmpctblock); -FUZZ_TARGET_MSG(feefilter); +FUZZ_TARGET_MSG(dsa); +FUZZ_TARGET_MSG(dsc); +FUZZ_TARGET_MSG(dsf); +FUZZ_TARGET_MSG(dsi); +FUZZ_TARGET_MSG(dsq); +FUZZ_TARGET_MSG(dss); +FUZZ_TARGET_MSG(dssu); +FUZZ_TARGET_MSG(dstx); FUZZ_TARGET_MSG(filteradd); FUZZ_TARGET_MSG(filterclear); FUZZ_TARGET_MSG(filterload); @@ -122,17 +139,47 @@ FUZZ_TARGET_MSG(getcfheaders); FUZZ_TARGET_MSG(getcfilters); FUZZ_TARGET_MSG(getdata); FUZZ_TARGET_MSG(getheaders); +FUZZ_TARGET_MSG(getheaders2); +FUZZ_TARGET_MSG(getmnlistd); +FUZZ_TARGET_MSG(getqrinfo); +FUZZ_TARGET_MSG(getsporks); +FUZZ_TARGET_MSG(govobj); +FUZZ_TARGET_MSG(govobjvote); +FUZZ_TARGET_MSG(govsync); FUZZ_TARGET_MSG(headers); +FUZZ_TARGET_MSG(headers2); FUZZ_TARGET_MSG(inv); +FUZZ_TARGET_MSG(isdlock); FUZZ_TARGET_MSG(mempool); FUZZ_TARGET_MSG(merkleblock); +FUZZ_TARGET_MSG(mnauth); +FUZZ_TARGET_MSG(mnlistdiff); FUZZ_TARGET_MSG(notfound); FUZZ_TARGET_MSG(ping); FUZZ_TARGET_MSG(pong); +FUZZ_TARGET_MSG(qbsigs); +FUZZ_TARGET_MSG(qcomplaint); +FUZZ_TARGET_MSG(qcontrib); +FUZZ_TARGET_MSG(qdata); +FUZZ_TARGET_MSG(qfcommit); +FUZZ_TARGET_MSG(qgetdata); +FUZZ_TARGET_MSG(qgetsigs); +FUZZ_TARGET_MSG(qjustify); +FUZZ_TARGET_MSG(qpcommit); +FUZZ_TARGET_MSG(qrinfo); +FUZZ_TARGET_MSG(qsendrecsigs); +FUZZ_TARGET_MSG(qsigrec); +FUZZ_TARGET_MSG(qsigsesann); +FUZZ_TARGET_MSG(qsigshare); +FUZZ_TARGET_MSG(qsigsinv); +FUZZ_TARGET_MSG(qwatch); FUZZ_TARGET_MSG(sendaddrv2); FUZZ_TARGET_MSG(sendcmpct); +FUZZ_TARGET_MSG(senddsq); FUZZ_TARGET_MSG(sendheaders); +FUZZ_TARGET_MSG(sendheaders2); +FUZZ_TARGET_MSG(spork); +FUZZ_TARGET_MSG(ssc); FUZZ_TARGET_MSG(tx); FUZZ_TARGET_MSG(verack); FUZZ_TARGET_MSG(version); -FUZZ_TARGET_MSG(wtxidrelay); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index dc035b52d61f..b61df25ed717 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -33,9 +34,12 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get(); - std::vector peers; + ConnmanTestMsg& connman = *static_cast(g_setup->m_node.connman.get()); + TestChainState& chainstate = *static_cast(&g_setup->m_node.chainman->ActiveChainstate()); + SetMockTime(1610000000); // any time to successfully reset ibd + chainstate.ResetIbd(); + std::vector peers; const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3); for (int i = 0; i < num_peers_to_add; ++i) { peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, i).release()); @@ -53,11 +57,14 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) while (fuzzed_data_provider.ConsumeBool()) { const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; + const auto mock_time = ConsumeTime(fuzzed_data_provider); + SetMockTime(mock_time); + 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(0, peers.size() - 1)); + CNode& random_node = *PickValue(fuzzed_data_provider, peers); (void)connman.ReceiveMsgFrom(random_node, net_msg); random_node.fPauseSend = false; diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp index b29f4e2228db..de0f7062434b 100644 --- a/src/test/fuzz/psbt.cpp +++ b/src/test/fuzz/psbt.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include @@ -9,6 +10,7 @@ #include #include