diff options
Diffstat (limited to 'src/test/fuzz')
-rw-r--r-- | src/test/fuzz/bech32.cpp | 43 | ||||
-rw-r--r-- | src/test/fuzz/deserialize.cpp | 318 | ||||
-rw-r--r-- | src/test/fuzz/eval_script.cpp | 9 | ||||
-rw-r--r-- | src/test/fuzz/parse_iso8601.cpp | 32 | ||||
-rw-r--r-- | src/test/fuzz/psbt.cpp | 79 | ||||
-rw-r--r-- | src/test/fuzz/script_flags.cpp | 7 | ||||
-rw-r--r-- | src/test/fuzz/transaction.cpp | 24 |
7 files changed, 403 insertions, 109 deletions
diff --git a/src/test/fuzz/bech32.cpp b/src/test/fuzz/bech32.cpp new file mode 100644 index 0000000000..8b91f9bc96 --- /dev/null +++ b/src/test/fuzz/bech32.cpp @@ -0,0 +1,43 @@ +// 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 <bech32.h> +#include <test/fuzz/fuzz.h> +#include <test/util/str.h> +#include <util/strencodings.h> + +#include <cassert> +#include <cstdint> +#include <string> +#include <utility> +#include <vector> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const std::string random_string(buffer.begin(), buffer.end()); + const std::pair<std::string, std::vector<uint8_t>> r1 = bech32::Decode(random_string); + if (r1.first.empty()) { + assert(r1.second.empty()); + } else { + const std::string& hrp = r1.first; + const std::vector<uint8_t>& data = r1.second; + const std::string reencoded = bech32::Encode(hrp, data); + assert(CaseInsensitiveEqual(random_string, reencoded)); + } + + std::vector<unsigned char> input; + ConvertBits<8, 5, true>([&](unsigned char c) { input.push_back(c); }, buffer.begin(), buffer.end()); + const std::string encoded = bech32::Encode("bc", input); + assert(!encoded.empty()); + + const std::pair<std::string, std::vector<uint8_t>> r2 = bech32::Decode(encoded); + if (r2.first.empty()) { + assert(r2.second.empty()); + } else { + const std::string& hrp = r2.first; + const std::vector<uint8_t>& data = r2.second; + assert(hrp == "bc"); + assert(data == input); + } +} diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index bcd8691359..46bc38fdab 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -5,18 +5,24 @@ #include <addrdb.h> #include <addrman.h> #include <blockencodings.h> +#include <blockfilter.h> #include <chain.h> #include <coins.h> #include <compressor.h> #include <consensus/merkle.h> +#include <key.h> +#include <merkleblock.h> #include <net.h> #include <primitives/block.h> #include <protocol.h> +#include <psbt.h> #include <pubkey.h> +#include <script/keyorigin.h> #include <streams.h> #include <undo.h> #include <version.h> +#include <stdexcept> #include <stdint.h> #include <unistd.h> @@ -37,129 +43,237 @@ void test_one_input(const std::vector<uint8_t>& buffer) int nVersion; ds >> nVersion; ds.SetVersion(nVersion); - } catch (const std::ios_base::failure& e) { + } catch (const std::ios_base::failure&) { return; } -#if BLOCK_DESERIALIZE - try - { - CBlock block; - ds >> block; - } catch (const std::ios_base::failure& e) {return;} +#if BLOCK_FILTER_DESERIALIZE + try { + BlockFilter block_filter; + ds >> block_filter; + } catch (const std::ios_base::failure&) { + } +#elif ADDR_INFO_DESERIALIZE + try { + CAddrInfo addr_info; + ds >> addr_info; + } catch (const std::ios_base::failure&) { + } +#elif BLOCK_FILE_INFO_DESERIALIZE + try { + CBlockFileInfo block_file_info; + ds >> block_file_info; + } catch (const std::ios_base::failure&) { + } +#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE + try { + CBlockHeaderAndShortTxIDs block_header_and_short_txids; + ds >> block_header_and_short_txids; + } catch (const std::ios_base::failure&) { + } +#elif FEE_RATE_DESERIALIZE + try { + CFeeRate fee_rate; + ds >> fee_rate; + } catch (const std::ios_base::failure&) { + } +#elif MERKLE_BLOCK_DESERIALIZE + try { + CMerkleBlock merkle_block; + ds >> merkle_block; + } catch (const std::ios_base::failure&) { + } +#elif OUT_POINT_DESERIALIZE + try { + COutPoint out_point; + ds >> out_point; + } catch (const std::ios_base::failure&) { + } +#elif PARTIAL_MERKLE_TREE_DESERIALIZE + try { + CPartialMerkleTree partial_merkle_tree; + ds >> partial_merkle_tree; + } catch (const std::ios_base::failure&) { + } +#elif PUB_KEY_DESERIALIZE + try { + CPubKey pub_key; + ds >> pub_key; + } catch (const std::ios_base::failure&) { + } +#elif SCRIPT_DESERIALIZE + try { + CScript script; + ds >> script; + } catch (const std::ios_base::failure&) { + } +#elif SUB_NET_DESERIALIZE + try { + CSubNet sub_net; + ds >> sub_net; + } catch (const std::ios_base::failure&) { + } +#elif TX_IN_DESERIALIZE + try { + CTxIn tx_in; + ds >> tx_in; + } catch (const std::ios_base::failure&) { + } +#elif FLAT_FILE_POS_DESERIALIZE + try { + FlatFilePos flat_file_pos; + ds >> flat_file_pos; + } catch (const std::ios_base::failure&) { + } +#elif KEY_ORIGIN_INFO_DESERIALIZE + try { + KeyOriginInfo key_origin_info; + ds >> key_origin_info; + } catch (const std::ios_base::failure&) { + } +#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE + try { + PartiallySignedTransaction partially_signed_transaction; + ds >> partially_signed_transaction; + } catch (const std::ios_base::failure&) { + } +#elif PREFILLED_TRANSACTION_DESERIALIZE + try { + PrefilledTransaction prefilled_transaction; + ds >> prefilled_transaction; + } catch (const std::ios_base::failure&) { + } +#elif PSBT_INPUT_DESERIALIZE + try { + PSBTInput psbt_input; + ds >> psbt_input; + } catch (const std::ios_base::failure&) { + } +#elif PSBT_OUTPUT_DESERIALIZE + try { + PSBTOutput psbt_output; + ds >> psbt_output; + } catch (const std::ios_base::failure&) { + } +#elif BLOCK_DESERIALIZE + try { + CBlock block; + ds >> block; + } catch (const std::ios_base::failure&) { + } #elif BLOCKLOCATOR_DESERIALIZE - try - { - CBlockLocator bl; - ds >> bl; - } catch (const std::ios_base::failure& e) {return;} + try { + CBlockLocator bl; + ds >> bl; + } catch (const std::ios_base::failure&) { + } #elif BLOCKMERKLEROOT - try - { - CBlock block; - ds >> block; - bool mutated; - BlockMerkleRoot(block, &mutated); - } catch (const std::ios_base::failure& e) {return;} + try { + CBlock block; + ds >> block; + bool mutated; + BlockMerkleRoot(block, &mutated); + } catch (const std::ios_base::failure&) { + } #elif ADDRMAN_DESERIALIZE - try - { - CAddrMan am; - ds >> am; - } catch (const std::ios_base::failure& e) {return;} + try { + CAddrMan am; + ds >> am; + } catch (const std::ios_base::failure&) { + } #elif BLOCKHEADER_DESERIALIZE - try - { - CBlockHeader bh; - ds >> bh; - } catch (const std::ios_base::failure& e) {return;} + try { + CBlockHeader bh; + ds >> bh; + } catch (const std::ios_base::failure&) { + } #elif BANENTRY_DESERIALIZE - try - { - CBanEntry be; - ds >> be; - } catch (const std::ios_base::failure& e) {return;} + try { + CBanEntry be; + ds >> be; + } catch (const std::ios_base::failure&) { + } #elif TXUNDO_DESERIALIZE - try - { - CTxUndo tu; - ds >> tu; - } catch (const std::ios_base::failure& e) {return;} + try { + CTxUndo tu; + ds >> tu; + } catch (const std::ios_base::failure&) { + } #elif BLOCKUNDO_DESERIALIZE - try - { - CBlockUndo bu; - ds >> bu; - } catch (const std::ios_base::failure& e) {return;} + try { + CBlockUndo bu; + ds >> bu; + } catch (const std::ios_base::failure&) { + } #elif COINS_DESERIALIZE - try - { - Coin coin; - ds >> coin; - } catch (const std::ios_base::failure& e) {return;} + try { + Coin coin; + ds >> coin; + } catch (const std::ios_base::failure&) { + } #elif NETADDR_DESERIALIZE - try - { - CNetAddr na; - ds >> na; - } catch (const std::ios_base::failure& e) {return;} + try { + CNetAddr na; + ds >> na; + } catch (const std::ios_base::failure&) { + } #elif SERVICE_DESERIALIZE - try - { - CService s; - ds >> s; - } catch (const std::ios_base::failure& e) {return;} + try { + CService s; + ds >> s; + } catch (const std::ios_base::failure&) { + } #elif MESSAGEHEADER_DESERIALIZE - CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00}; - try - { - CMessageHeader mh(pchMessageStart); - ds >> mh; - if (!mh.IsValid(pchMessageStart)) {return;} - } catch (const std::ios_base::failure& e) {return;} + CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00}; + try { + CMessageHeader mh(pchMessageStart); + ds >> mh; + (void)mh.IsValid(pchMessageStart); + } catch (const std::ios_base::failure&) { + } #elif ADDRESS_DESERIALIZE - try - { - CAddress a; - ds >> a; - } catch (const std::ios_base::failure& e) {return;} + try { + CAddress a; + ds >> a; + } catch (const std::ios_base::failure&) { + } #elif INV_DESERIALIZE - try - { - CInv i; - ds >> i; - } catch (const std::ios_base::failure& e) {return;} + try { + CInv i; + ds >> i; + } catch (const std::ios_base::failure&) { + } #elif BLOOMFILTER_DESERIALIZE - try - { - CBloomFilter bf; - ds >> bf; - } catch (const std::ios_base::failure& e) {return;} + try { + CBloomFilter bf; + ds >> bf; + } catch (const std::ios_base::failure&) { + } #elif DISKBLOCKINDEX_DESERIALIZE - try - { - CDiskBlockIndex dbi; - ds >> dbi; - } catch (const std::ios_base::failure& e) {return;} + try { + CDiskBlockIndex dbi; + ds >> dbi; + } catch (const std::ios_base::failure&) { + } #elif TXOUTCOMPRESSOR_DESERIALIZE - CTxOut to; - CTxOutCompressor toc(to); - try - { - ds >> toc; - } catch (const std::ios_base::failure& e) {return;} + CTxOut to; + CTxOutCompressor toc(to); + try { + ds >> toc; + } catch (const std::ios_base::failure&) { + } #elif BLOCKTRANSACTIONS_DESERIALIZE - try - { - BlockTransactions bt; - ds >> bt; - } catch (const std::ios_base::failure& e) {return;} + try { + BlockTransactions bt; + ds >> bt; + } catch (const std::ios_base::failure&) { + } #elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE - try - { - BlockTransactionsRequest btr; - ds >> btr; - } catch (const std::ios_base::failure& e) {return;} + try { + BlockTransactionsRequest btr; + ds >> btr; + } catch (const std::ios_base::failure&) { + } #else #error Need at least one fuzz target to compile #endif diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp index 9444cd489e..7acdd76857 100644 --- a/src/test/fuzz/eval_script.cpp +++ b/src/test/fuzz/eval_script.cpp @@ -2,12 +2,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <pubkey.h> #include <script/interpreter.h> -#include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <util/memory.h> #include <limits> +void initialize() +{ + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + void test_one_input(const std::vector<uint8_t>& buffer) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); diff --git a/src/test/fuzz/parse_iso8601.cpp b/src/test/fuzz/parse_iso8601.cpp new file mode 100644 index 0000000000..c86f8a853e --- /dev/null +++ b/src/test/fuzz/parse_iso8601.cpp @@ -0,0 +1,32 @@ +// 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 <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <util/time.h> + +#include <cassert> +#include <cstdint> +#include <string> +#include <vector> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + const int64_t random_time = fuzzed_data_provider.ConsumeIntegral<int64_t>(); + const std::string random_string = fuzzed_data_provider.ConsumeRemainingBytesAsString(); + + const std::string iso8601_datetime = FormatISO8601DateTime(random_time); + const int64_t parsed_time_1 = ParseISO8601DateTime(iso8601_datetime); + if (random_time >= 0) { + assert(parsed_time_1 >= 0); + if (iso8601_datetime.length() == 20) { + assert(parsed_time_1 == random_time); + } + } + + const int64_t parsed_time_2 = ParseISO8601DateTime(random_string); + assert(parsed_time_2 >= 0); +} diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp new file mode 100644 index 0000000000..1ce28f9a6d --- /dev/null +++ b/src/test/fuzz/psbt.cpp @@ -0,0 +1,79 @@ +// 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 <test/fuzz/fuzz.h> + +#include <node/psbt.h> +#include <optional.h> +#include <psbt.h> +#include <pubkey.h> +#include <script/script.h> +#include <streams.h> +#include <util/memory.h> +#include <version.h> + +#include <cstdint> +#include <string> +#include <vector> + +void initialize() +{ + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + PartiallySignedTransaction psbt_mut; + const std::string raw_psbt{buffer.begin(), buffer.end()}; + std::string error; + if (!DecodeRawPSBT(psbt_mut, raw_psbt, error)) { + return; + } + const PartiallySignedTransaction psbt = psbt_mut; + + const PSBTAnalysis analysis = AnalyzePSBT(psbt); + (void)PSBTRoleName(analysis.next); + for (const PSBTInputAnalysis& input_analysis : analysis.inputs) { + (void)PSBTRoleName(input_analysis.next); + } + + (void)psbt.IsNull(); + (void)psbt.IsSane(); + + Optional<CMutableTransaction> tx = psbt.tx; + if (tx) { + const CMutableTransaction& mtx = *tx; + const PartiallySignedTransaction psbt_from_tx{mtx}; + } + + for (const PSBTInput& input : psbt.inputs) { + (void)PSBTInputSigned(input); + (void)input.IsNull(); + (void)input.IsSane(); + } + + for (const PSBTOutput& output : psbt.outputs) { + (void)output.IsNull(); + } + + for (size_t i = 0; i < psbt.tx->vin.size(); ++i) { + CTxOut tx_out; + if (psbt.GetInputUTXO(tx_out, i)) { + (void)tx_out.IsNull(); + (void)tx_out.ToString(); + } + } + + psbt_mut = psbt; + (void)FinalizePSBT(psbt_mut); + + psbt_mut = psbt; + CMutableTransaction result; + if (FinalizeAndExtractPSBT(psbt_mut, result)) { + const PartiallySignedTransaction psbt_from_tx{result}; + } + + psbt_mut = psbt; + (void)psbt_mut.Merge(psbt); +} diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp index 0bf5cd5c72..08622d0979 100644 --- a/src/test/fuzz/script_flags.cpp +++ b/src/test/fuzz/script_flags.cpp @@ -2,8 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <pubkey.h> #include <script/interpreter.h> #include <streams.h> +#include <util/memory.h> #include <version.h> #include <test/fuzz/fuzz.h> @@ -11,6 +13,11 @@ /** Flags that are not forbidden by an assert */ static bool IsValidFlagCombination(unsigned flags); +void initialize() +{ + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); +} + void test_one_input(const std::vector<uint8_t>& buffer) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index 383d879040..fefafda36b 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -26,23 +26,35 @@ void test_one_input(const std::vector<uint8_t>& buffer) int nVersion; ds >> nVersion; ds.SetVersion(nVersion); - } catch (const std::ios_base::failure& e) { + } catch (const std::ios_base::failure&) { return; } - bool valid = true; + bool valid_tx = true; const CTransaction tx = [&] { try { return CTransaction(deserialize, ds); - } catch (const std::ios_base::failure& e) { - valid = false; + } catch (const std::ios_base::failure&) { + valid_tx = false; return CTransaction(); } }(); - if (!valid) { + bool valid_mutable_tx = true; + CDataStream ds_mtx(buffer, SER_NETWORK, INIT_PROTO_VERSION); + CMutableTransaction mutable_tx; + try { + int nVersion; + ds_mtx >> nVersion; + ds_mtx.SetVersion(nVersion); + ds_mtx >> mutable_tx; + } catch (const std::ios_base::failure&) { + valid_mutable_tx = false; + } + assert(valid_tx == valid_mutable_tx); + if (!valid_tx) { return; } - CValidationState state_with_dupe_check; + TxValidationState state_with_dupe_check; (void)CheckTransaction(tx, state_with_dupe_check); const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE}; |