git / moonbite-core / src/test/fuzz/deserialize.cpp · raw
// Copyright (c) 2009-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 <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 <netbase.h>#include <node/utxo_snapshot.h>#include <optional.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 <exception>#include <stdexcept>#include <stdint.h>#include <unistd.h>#include <vector>#include <test/fuzz/fuzz.h>void initialize(){ // Fuzzers using pubkey must hold an ECCVerifyHandle. static const ECCVerifyHandle verify_handle;}namespace {struct invalid_fuzzing_input_exception : public std::exception {};template <typename T>CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION){ CDataStream ds(SER_NETWORK, version); ds << obj; return ds;}template <typename T>T Deserialize(CDataStream ds){ T obj; ds >> obj; return obj;}template <typename T>void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj, const Optional<int> protocol_version = nullopt){ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); if (protocol_version) { ds.SetVersion(*protocol_version); } else { try { int version; ds >> version; ds.SetVersion(version); } catch (const std::ios_base::failure&) { throw invalid_fuzzing_input_exception(); } } try { ds >> obj; } catch (const std::ios_base::failure&) { throw invalid_fuzzing_input_exception(); } assert(buffer.empty() || !Serialize(obj).empty());}template <typename T>void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION){ assert(Deserialize<T>(Serialize(obj, version)) == obj);}} // namespacevoid test_one_input(const std::vector<uint8_t>& buffer){ try {#if BLOCK_FILTER_DESERIALIZE BlockFilter block_filter; DeserializeFromFuzzingInput(buffer, block_filter);#elif ADDR_INFO_DESERIALIZE CAddrInfo addr_info; DeserializeFromFuzzingInput(buffer, addr_info);#elif BLOCK_FILE_INFO_DESERIALIZE CBlockFileInfo block_file_info; DeserializeFromFuzzingInput(buffer, block_file_info);#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE CBlockHeaderAndShortTxIDs block_header_and_short_txids; DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);#elif FEE_RATE_DESERIALIZE CFeeRate fee_rate; DeserializeFromFuzzingInput(buffer, fee_rate); AssertEqualAfterSerializeDeserialize(fee_rate);#elif MERKLE_BLOCK_DESERIALIZE CMerkleBlock merkle_block; DeserializeFromFuzzingInput(buffer, merkle_block);#elif OUT_POINT_DESERIALIZE COutPoint out_point; DeserializeFromFuzzingInput(buffer, out_point); AssertEqualAfterSerializeDeserialize(out_point);#elif PARTIAL_MERKLE_TREE_DESERIALIZE CPartialMerkleTree partial_merkle_tree; DeserializeFromFuzzingInput(buffer, partial_merkle_tree);#elif PUB_KEY_DESERIALIZE CPubKey pub_key; DeserializeFromFuzzingInput(buffer, pub_key); // TODO: The following equivalence should hold for CPubKey? Fix. // AssertEqualAfterSerializeDeserialize(pub_key);#elif SCRIPT_DESERIALIZE CScript script; DeserializeFromFuzzingInput(buffer, script);#elif SUB_NET_DESERIALIZE CSubNet sub_net_1; DeserializeFromFuzzingInput(buffer, sub_net_1, INIT_PROTO_VERSION); AssertEqualAfterSerializeDeserialize(sub_net_1, INIT_PROTO_VERSION); CSubNet sub_net_2; DeserializeFromFuzzingInput(buffer, sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); AssertEqualAfterSerializeDeserialize(sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); CSubNet sub_net_3; DeserializeFromFuzzingInput(buffer, sub_net_3); AssertEqualAfterSerializeDeserialize(sub_net_3, INIT_PROTO_VERSION | ADDRV2_FORMAT);#elif TX_IN_DESERIALIZE CTxIn tx_in; DeserializeFromFuzzingInput(buffer, tx_in); AssertEqualAfterSerializeDeserialize(tx_in);#elif FLAT_FILE_POS_DESERIALIZE FlatFilePos flat_file_pos; DeserializeFromFuzzingInput(buffer, flat_file_pos); AssertEqualAfterSerializeDeserialize(flat_file_pos);#elif KEY_ORIGIN_INFO_DESERIALIZE KeyOriginInfo key_origin_info; DeserializeFromFuzzingInput(buffer, key_origin_info); AssertEqualAfterSerializeDeserialize(key_origin_info);#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE PartiallySignedTransaction partially_signed_transaction; DeserializeFromFuzzingInput(buffer, partially_signed_transaction);#elif PREFILLED_TRANSACTION_DESERIALIZE PrefilledTransaction prefilled_transaction; DeserializeFromFuzzingInput(buffer, prefilled_transaction);#elif PSBT_INPUT_DESERIALIZE PSBTInput psbt_input; DeserializeFromFuzzingInput(buffer, psbt_input);#elif PSBT_OUTPUT_DESERIALIZE PSBTOutput psbt_output; DeserializeFromFuzzingInput(buffer, psbt_output);#elif BLOCK_DESERIALIZE CBlock block; DeserializeFromFuzzingInput(buffer, block);#elif BLOCKLOCATOR_DESERIALIZE CBlockLocator bl; DeserializeFromFuzzingInput(buffer, bl);#elif BLOCKMERKLEROOT CBlock block; DeserializeFromFuzzingInput(buffer, block); bool mutated; BlockMerkleRoot(block, &mutated);#elif ADDRMAN_DESERIALIZE CAddrMan am; DeserializeFromFuzzingInput(buffer, am);#elif BLOCKHEADER_DESERIALIZE CBlockHeader bh; DeserializeFromFuzzingInput(buffer, bh);#elif BANENTRY_DESERIALIZE CBanEntry be; DeserializeFromFuzzingInput(buffer, be);#elif TXUNDO_DESERIALIZE CTxUndo tu; DeserializeFromFuzzingInput(buffer, tu);#elif BLOCKUNDO_DESERIALIZE CBlockUndo bu; DeserializeFromFuzzingInput(buffer, bu);#elif COINS_DESERIALIZE Coin coin; DeserializeFromFuzzingInput(buffer, coin);#elif NETADDR_DESERIALIZE CNetAddr na; DeserializeFromFuzzingInput(buffer, na); if (na.IsAddrV1Compatible()) { AssertEqualAfterSerializeDeserialize(na); } AssertEqualAfterSerializeDeserialize(na, INIT_PROTO_VERSION | ADDRV2_FORMAT);#elif SERVICE_DESERIALIZE CService s; DeserializeFromFuzzingInput(buffer, s); if (s.IsAddrV1Compatible()) { AssertEqualAfterSerializeDeserialize(s); } AssertEqualAfterSerializeDeserialize(s, INIT_PROTO_VERSION | ADDRV2_FORMAT); CService s1; DeserializeFromFuzzingInput(buffer, s1, INIT_PROTO_VERSION); AssertEqualAfterSerializeDeserialize(s1, INIT_PROTO_VERSION); assert(s1.IsAddrV1Compatible()); CService s2; DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT);#elif MESSAGEHEADER_DESERIALIZE CMessageHeader mh; DeserializeFromFuzzingInput(buffer, mh); (void)mh.IsCommandValid();#elif ADDRESS_DESERIALIZE CAddress a; DeserializeFromFuzzingInput(buffer, a);#elif INV_DESERIALIZE CInv i; DeserializeFromFuzzingInput(buffer, i);#elif BLOOMFILTER_DESERIALIZE CBloomFilter bf; DeserializeFromFuzzingInput(buffer, bf);#elif DISKBLOCKINDEX_DESERIALIZE CDiskBlockIndex dbi; DeserializeFromFuzzingInput(buffer, dbi);#elif TXOUTCOMPRESSOR_DESERIALIZE CTxOut to; auto toc = Using<TxOutCompression>(to); DeserializeFromFuzzingInput(buffer, toc);#elif BLOCKTRANSACTIONS_DESERIALIZE BlockTransactions bt; DeserializeFromFuzzingInput(buffer, bt);#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE BlockTransactionsRequest btr; DeserializeFromFuzzingInput(buffer, btr);#elif SNAPSHOTMETADATA_DESERIALIZE SnapshotMetadata snapshot_metadata; DeserializeFromFuzzingInput(buffer, snapshot_metadata);#elif UINT160_DESERIALIZE uint160 u160; DeserializeFromFuzzingInput(buffer, u160); AssertEqualAfterSerializeDeserialize(u160);#elif UINT256_DESERIALIZE uint256 u256; DeserializeFromFuzzingInput(buffer, u256); AssertEqualAfterSerializeDeserialize(u256);#else#error Need at least one fuzz target to compile#endif // Classes intentionally not covered in this file since their deserialization code is // fuzzed elsewhere: // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp } catch (const invalid_fuzzing_input_exception&) { }}