diff options
Diffstat (limited to 'src/test/fuzz')
-rw-r--r-- | src/test/fuzz/deserialize.cpp | 167 | ||||
-rw-r--r-- | src/test/fuzz/script_flags.cpp | 72 |
2 files changed, 239 insertions, 0 deletions
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp new file mode 100644 index 0000000000..859fba0bdc --- /dev/null +++ b/src/test/fuzz/deserialize.cpp @@ -0,0 +1,167 @@ +// Copyright (c) 2009-2018 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 <addrman.h> +#include <blockencodings.h> +#include <chain.h> +#include <coins.h> +#include <compressor.h> +#include <consensus/merkle.h> +#include <net.h> +#include <primitives/block.h> +#include <protocol.h> +#include <pubkey.h> +#include <script/script.h> +#include <streams.h> +#include <undo.h> +#include <version.h> + +#include <stdint.h> +#include <unistd.h> + +#include <algorithm> +#include <memory> +#include <vector> + +#include <test/fuzz/fuzz.h> + +void test_one_input(std::vector<uint8_t> 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; + } + +#if BLOCK_DESERIALIZE + try + { + CBlock block; + ds >> block; + } 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; + ds >> bl; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKMERKLEROOT + try + { + CBlock block; + ds >> block; + bool mutated; + BlockMerkleRoot(block, &mutated); + } catch (const std::ios_base::failure& e) {return;} +#elif ADDRMAN_DESERIALIZE + try + { + CAddrMan am; + ds >> am; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKHEADER_DESERIALIZE + try + { + CBlockHeader bh; + ds >> bh; + } catch (const std::ios_base::failure& e) {return;} +#elif BANENTRY_DESERIALIZE + try + { + CBanEntry be; + ds >> be; + } catch (const std::ios_base::failure& e) {return;} +#elif TXUNDO_DESERIALIZE + try + { + CTxUndo tu; + ds >> tu; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKUNDO_DESERIALIZE + try + { + CBlockUndo bu; + ds >> bu; + } catch (const std::ios_base::failure& e) {return;} +#elif COINS_DESERIALIZE + try + { + Coin coin; + ds >> coin; + } catch (const std::ios_base::failure& e) {return;} +#elif NETADDR_DESERIALIZE + try + { + CNetAddr na; + ds >> na; + } catch (const std::ios_base::failure& e) {return;} +#elif SERVICE_DESERIALIZE + try + { + CService s; + ds >> s; + } catch (const std::ios_base::failure& e) {return;} +#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;} +#elif ADDRESS_DESERIALIZE + try + { + CAddress a; + ds >> a; + } catch (const std::ios_base::failure& e) {return;} +#elif INV_DESERIALIZE + try + { + CInv i; + ds >> i; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOOMFILTER_DESERIALIZE + try + { + CBloomFilter bf; + ds >> bf; + } catch (const std::ios_base::failure& e) {return;} +#elif DISKBLOCKINDEX_DESERIALIZE + try + { + CDiskBlockIndex dbi; + ds >> dbi; + } catch (const std::ios_base::failure& e) {return;} +#elif TXOUTCOMPRESSOR_DESERIALIZE + CTxOut to; + CTxOutCompressor toc(to); + try + { + ds >> toc; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKTRANSACTIONS_DESERIALIZE + try + { + BlockTransactions bt; + ds >> bt; + } catch (const std::ios_base::failure& e) {return;} +#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE + try + { + BlockTransactionsRequest btr; + ds >> btr; + } catch (const std::ios_base::failure& e) {return;} +#else +#error Need at least one fuzz target to compile +#endif +} diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp new file mode 100644 index 0000000000..2c0bfa360c --- /dev/null +++ b/src/test/fuzz/script_flags.cpp @@ -0,0 +1,72 @@ +// Copyright (c) 2009-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 <script/interpreter.h> +#include <script/script.h> +#include <streams.h> +#include <version.h> + +#include <test/fuzz/fuzz.h> + +/** Flags that are not forbidden by an assert */ +static bool IsValidFlagCombination(unsigned flags); + +void test_one_input(std::vector<uint8_t> buffer) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + try { + int nVersion; + ds >> nVersion; + ds.SetVersion(nVersion); + } catch (const std::ios_base::failure&) { + return; + } + + try { + const CTransaction tx(deserialize, ds); + const PrecomputedTransactionData txdata(tx); + + unsigned int verify_flags; + ds >> verify_flags; + + if (!IsValidFlagCombination(verify_flags)) return; + + unsigned int fuzzed_flags; + ds >> fuzzed_flags; + + for (unsigned i = 0; i < tx.vin.size(); ++i) { + CTxOut prevout; + ds >> prevout; + + const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata}; + + ScriptError serror; + const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror); + assert(ret == (serror == SCRIPT_ERR_OK)); + + // Verify that removing flags from a passing test or adding flags to a failing test does not change the result + if (ret) { + verify_flags &= ~fuzzed_flags; + } else { + verify_flags |= fuzzed_flags; + } + if (!IsValidFlagCombination(verify_flags)) return; + + ScriptError serror_fuzzed; + const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed); + assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK)); + + assert(ret_fuzzed == ret); + } + } catch (const std::ios_base::failure&) { + return; + } +} + +static bool IsValidFlagCombination(unsigned flags) +{ + if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; + if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; + return true; +} |