diff --git a/src/Makefile.test.include b/src/Makefile.test.include --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -22,7 +22,7 @@ test/fuzz/netaddr_deserialize \ test/fuzz/script_flags \ test/fuzz/service_deserialize \ - test/fuzz/transaction_deserialize \ + test/fuzz/transaction \ test/fuzz/txoutcompressor_deserialize \ test/fuzz/txundo_deserialize @@ -241,12 +241,6 @@ test_fuzz_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) -test_fuzz_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp -test_fuzz_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTRANSACTION_DESERIALIZE=1 -test_fuzz_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_fuzz_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) - test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1 test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -360,6 +354,13 @@ test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) + +test_fuzz_transaction_SOURCES = $(FUZZ_SUITE) test/fuzz/transaction.cpp +test_fuzz_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_transaction_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON) + endif # ENABLE_FUZZ nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -46,7 +46,7 @@ add_dependencies(check check-bitcoin) # An utility library for bitcoin related test suites. -add_library(testutil +add_library(testutil OBJECT util/blockfilter.cpp util/logging.cpp util/setup_common.cpp 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 @@ -13,6 +13,19 @@ add_dependencies(bitcoin-fuzzers ${TARGET}) endmacro() +function(add_regular_fuzz_targets) + foreach(_fuzz_test_name ${ARGN}) + sanitize_target_name("fuzz-" ${_fuzz_test_name} _fuzz_target_name) + add_fuzz_target( + ${_fuzz_target_name} + ${_fuzz_test_name} + + # Sources + "${_fuzz_test_name}.cpp" + ) + endforeach() +endfunction() + include(SanitizeHelper) function(add_deserialize_fuzz_targets) foreach(_fuzz_test_name ${ARGN}) @@ -31,6 +44,11 @@ endforeach() endfunction() +add_regular_fuzz_targets( + script_flags + transaction +) + add_deserialize_fuzz_targets( address_deserialize addrman_deserialize @@ -49,16 +67,6 @@ messageheader_deserialize netaddr_deserialize service_deserialize - transaction_deserialize txoutcompressor_deserialize txundo_deserialize -) - -add_fuzz_target( - fuzz-script_flags - script_flags - - # Sources - fuzz.cpp - script_flags.cpp -) +) \ No newline at end of file diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -39,12 +39,6 @@ } catch (const std::ios_base::failure &e) { return; } -#elif TRANSACTION_DESERIALIZE - try { - CTransaction tx(deserialize, ds); - } catch (const std::ios_base::failure &e) { - return; - } #elif BLOCKLOCATOR_DESERIALIZE try { CBlockLocator bl; diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp new file mode 100644 --- /dev/null +++ b/src/test/fuzz/transaction.cpp @@ -0,0 +1,74 @@ +// Copyright (c) 2019 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +void test_one_input(const std::vector &buffer) { + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + try { + int nVersion; + ds >> nVersion; + ds.SetVersion(nVersion); + } catch (const std::ios_base::failure &e) { + return; + } + bool valid = true; + const CTransaction tx = [&] { + try { + return CTransaction(deserialize, ds); + } catch (const std::ios_base::failure &e) { + valid = false; + return CTransaction(); + } + }(); + if (!valid) { + return; + } + + CValidationState state; + (void)CheckRegularTransaction(tx, state); + + const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE}; + std::string reason; + const bool is_standard_with_permit_bare_multisig = IsStandardTx( + tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason); + const bool is_standard_without_permit_bare_multisig = IsStandardTx( + tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason); + if (is_standard_without_permit_bare_multisig) { + assert(is_standard_with_permit_bare_multisig); + } + std::unique_ptr params = + CreateChainParams(CBaseChainParams::REGTEST); + (void)tx.GetHash(); + (void)tx.GetTotalSize(); + try { + (void)tx.GetValueOut(); + } catch (const std::runtime_error &) { + } + (void)tx.IsCoinBase(); + (void)tx.IsNull(); + (void)tx.ToString(); + + (void)EncodeHexTx(tx); + (void)GetVirtualTransactionSize(tx); + (void)ContextualCheckTransaction(params->GetConsensus(), tx, state, 1024, + 1024, 0); + (void)IsStandardTx(tx, reason); + (void)RecursiveDynamicUsage(tx); +}