LCOV - code coverage report
Current view: top level - src/test/fuzz - deserialize.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 43 128 33.6 %
Date: 2023-09-26 12:08:55 Functions: 80 210 38.1 %

          Line data    Source code
       1             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <addrdb.h>
       6             : #include <addrman.h>
       7             : #include <addrman_impl.h>
       8             : #include <blockencodings.h>
       9             : #include <blockfilter.h>
      10             : #include <chain.h>
      11             : #include <coins.h>
      12             : #include <common/args.h>
      13             : #include <compressor.h>
      14             : #include <consensus/merkle.h>
      15             : #include <key.h>
      16             : #include <merkleblock.h>
      17           2 : #include <net.h>
      18           2 : #include <netbase.h>
      19             : #include <netgroup.h>
      20             : #include <node/utxo_snapshot.h>
      21             : #include <primitives/block.h>
      22             : #include <protocol.h>
      23             : #include <psbt.h>
      24             : #include <pubkey.h>
      25             : #include <script/keyorigin.h>
      26             : #include <streams.h>
      27           2 : #include <test/fuzz/fuzz.h>
      28             : #include <test/fuzz/util.h>
      29             : #include <test/util/setup_common.h>
      30             : #include <undo.h>
      31             : #include <version.h>
      32             : 
      33             : #include <exception>
      34             : #include <optional>
      35             : #include <stdexcept>
      36             : #include <stdint.h>
      37             : #include <unistd.h>
      38             : 
      39             : using node::SnapshotMetadata;
      40             : 
      41             : namespace {
      42             : const BasicTestingSetup* g_setup;
      43             : } // namespace
      44             : 
      45           0 : void initialize_deserialize()
      46             : {
      47           0 :     static const auto testing_setup = MakeNoLogFileContext<>();
      48           0 :     g_setup = testing_setup.get();
      49           0 : }
      50             : 
      51           2 : #define FUZZ_TARGET_DESERIALIZE(name, code)                \
      52             :     FUZZ_TARGET(name, .init = initialize_deserialize)         \
      53             :     {                                                      \
      54             :         try {                                              \
      55             :             code                                           \
      56             :         } catch (const invalid_fuzzing_input_exception&) { \
      57             :         }                                                  \
      58             :     }
      59             : 
      60             : namespace {
      61             : 
      62             : struct invalid_fuzzing_input_exception : public std::exception {
      63             : };
      64             : 
      65             : template <typename T, typename P>
      66           0 : DataStream Serialize(const T& obj, const P& params)
      67             : {
      68           0 :     DataStream ds{};
      69           0 :     ds << WithParams(params, obj);
      70           0 :     return ds;
      71           0 : }
      72             : 
      73             : template <typename T, typename P>
      74           2 : T Deserialize(DataStream&& ds, const P& params)
      75             : {
      76           0 :     T obj;
      77           0 :     ds >> WithParams(params, obj);
      78           0 :     return obj;
      79           0 : }
      80             : 
      81             : template <typename T, typename P>
      82             : void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj, const P& params)
      83           2 : {
      84             :     DataStream ds{buffer};
      85             :     try {
      86             :         ds >> WithParams(params, obj);
      87             :     } catch (const std::ios_base::failure&) {
      88             :         throw invalid_fuzzing_input_exception();
      89             :     }
      90             :     assert(buffer.empty() || !Serialize(obj, params).empty());
      91             : }
      92             : 
      93             : template <typename T>
      94           0 : CDataStream Serialize(const T& obj)
      95             : {
      96           0 :     CDataStream ds{SER_NETWORK, INIT_PROTO_VERSION};
      97           0 :     ds << obj;
      98           0 :     return ds;
      99           0 : }
     100             : 
     101             : template <typename T>
     102           0 : T Deserialize(CDataStream ds)
     103             : {
     104           0 :     T obj;
     105           0 :     ds >> obj;
     106           0 :     return obj;
     107           0 : }
     108             : 
     109             : template <typename T>
     110           0 : void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj)
     111             : {
     112           0 :     CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
     113             :     {
     114             :         try {
     115             :             int version;
     116           0 :             ds >> version;
     117           0 :             ds.SetVersion(version);
     118           0 :         } catch (const std::ios_base::failure&) {
     119           0 :             throw invalid_fuzzing_input_exception();
     120           0 :         }
     121             :     }
     122             :     try {
     123           0 :         ds >> obj;
     124           0 :     } catch (const std::ios_base::failure&) {
     125           0 :         throw invalid_fuzzing_input_exception();
     126           0 :     }
     127           0 :     assert(buffer.empty() || !Serialize(obj).empty());
     128           0 : }
     129             : 
     130             : template <typename T, typename P>
     131           0 : void AssertEqualAfterSerializeDeserialize(const T& obj, const P& params)
     132             : {
     133           0 :     assert(Deserialize<T>(Serialize(obj, params), params) == obj);
     134           0 : }
     135             : template <typename T>
     136           0 : void AssertEqualAfterSerializeDeserialize(const T& obj)
     137             : {
     138           0 :     assert(Deserialize<T>(Serialize(obj)) == obj);
     139           0 : }
     140             : 
     141             : } // namespace
     142             : 
     143           4 : FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
     144             :     BlockFilter block_filter;
     145             :     DeserializeFromFuzzingInput(buffer, block_filter);
     146             : })
     147           4 : FUZZ_TARGET(addr_info_deserialize, .init = initialize_deserialize)
     148             : {
     149           0 :     FuzzedDataProvider fdp{buffer.data(), buffer.size()};
     150           0 :     (void)ConsumeDeserializable<AddrInfo>(fdp, ConsumeDeserializationParams<CAddress::SerParams>(fdp));
     151           0 : }
     152           4 : FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
     153             :     CBlockFileInfo block_file_info;
     154             :     DeserializeFromFuzzingInput(buffer, block_file_info);
     155             : })
     156           4 : FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
     157             :     CBlockHeaderAndShortTxIDs block_header_and_short_txids;
     158             :     DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
     159             : })
     160           4 : FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
     161             :     CFeeRate fee_rate;
     162             :     DeserializeFromFuzzingInput(buffer, fee_rate);
     163             :     AssertEqualAfterSerializeDeserialize(fee_rate);
     164             : })
     165           4 : FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
     166             :     CMerkleBlock merkle_block;
     167             :     DeserializeFromFuzzingInput(buffer, merkle_block);
     168             : })
     169           4 : FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
     170             :     COutPoint out_point;
     171             :     DeserializeFromFuzzingInput(buffer, out_point);
     172             :     AssertEqualAfterSerializeDeserialize(out_point);
     173             : })
     174           4 : FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
     175             :     CPartialMerkleTree partial_merkle_tree;
     176             :     DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
     177             : })
     178           4 : FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
     179             :     CPubKey pub_key;
     180             :     DeserializeFromFuzzingInput(buffer, pub_key);
     181             :     AssertEqualAfterSerializeDeserialize(pub_key);
     182             : })
     183           4 : FUZZ_TARGET_DESERIALIZE(script_deserialize, {
     184             :     CScript script;
     185             :     DeserializeFromFuzzingInput(buffer, script);
     186             : })
     187           4 : FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
     188             :     CTxIn tx_in;
     189             :     DeserializeFromFuzzingInput(buffer, tx_in);
     190             :     AssertEqualAfterSerializeDeserialize(tx_in);
     191             : })
     192           4 : FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
     193             :     FlatFilePos flat_file_pos;
     194             :     DeserializeFromFuzzingInput(buffer, flat_file_pos);
     195             :     AssertEqualAfterSerializeDeserialize(flat_file_pos);
     196             : })
     197           4 : FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
     198             :     KeyOriginInfo key_origin_info;
     199             :     DeserializeFromFuzzingInput(buffer, key_origin_info);
     200             :     AssertEqualAfterSerializeDeserialize(key_origin_info);
     201             : })
     202           4 : FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
     203             :     PartiallySignedTransaction partially_signed_transaction;
     204             :     DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
     205             : })
     206           4 : FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
     207             :     PrefilledTransaction prefilled_transaction;
     208             :     DeserializeFromFuzzingInput(buffer, prefilled_transaction);
     209             : })
     210           4 : FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
     211             :     PSBTInput psbt_input;
     212             :     DeserializeFromFuzzingInput(buffer, psbt_input);
     213             : })
     214           4 : FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
     215             :     PSBTOutput psbt_output;
     216             :     DeserializeFromFuzzingInput(buffer, psbt_output);
     217             : })
     218           4 : FUZZ_TARGET_DESERIALIZE(block_deserialize, {
     219             :     CBlock block;
     220             :     DeserializeFromFuzzingInput(buffer, block);
     221             : })
     222           4 : FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
     223             :     CBlockLocator bl;
     224             :     DeserializeFromFuzzingInput(buffer, bl);
     225             : })
     226           4 : FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
     227             :     CBlock block;
     228             :     DeserializeFromFuzzingInput(buffer, block);
     229             :     bool mutated;
     230             :     BlockMerkleRoot(block, &mutated);
     231             : })
     232           4 : FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
     233             :     CBlockHeader bh;
     234             :     DeserializeFromFuzzingInput(buffer, bh);
     235             : })
     236           4 : FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
     237             :     CTxUndo tu;
     238             :     DeserializeFromFuzzingInput(buffer, tu);
     239             : })
     240           4 : FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
     241             :     CBlockUndo bu;
     242             :     DeserializeFromFuzzingInput(buffer, bu);
     243             : })
     244           4 : FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
     245             :     Coin coin;
     246             :     DeserializeFromFuzzingInput(buffer, coin);
     247             : })
     248           4 : FUZZ_TARGET(netaddr_deserialize, .init = initialize_deserialize)
     249             : {
     250           0 :     FuzzedDataProvider fdp{buffer.data(), buffer.size()};
     251           0 :     const auto maybe_na{ConsumeDeserializable<CNetAddr>(fdp, ConsumeDeserializationParams<CNetAddr::SerParams>(fdp))};
     252           0 :     if (!maybe_na) return;
     253           0 :     const CNetAddr& na{*maybe_na};
     254           0 :     if (na.IsAddrV1Compatible()) {
     255           0 :         AssertEqualAfterSerializeDeserialize(na, CNetAddr::V1);
     256           0 :     }
     257           0 :     AssertEqualAfterSerializeDeserialize(na, CNetAddr::V2);
     258           0 : }
     259           4 : FUZZ_TARGET(service_deserialize, .init = initialize_deserialize)
     260             : {
     261           0 :     FuzzedDataProvider fdp{buffer.data(), buffer.size()};
     262           0 :     const auto ser_params{ConsumeDeserializationParams<CNetAddr::SerParams>(fdp)};
     263           0 :     const auto maybe_s{ConsumeDeserializable<CService>(fdp, ser_params)};
     264           0 :     if (!maybe_s) return;
     265           0 :     const CService& s{*maybe_s};
     266           0 :     if (s.IsAddrV1Compatible()) {
     267           0 :         AssertEqualAfterSerializeDeserialize(s, CNetAddr::V1);
     268           0 :     }
     269           0 :     AssertEqualAfterSerializeDeserialize(s, CNetAddr::V2);
     270           0 :     if (ser_params.enc == CNetAddr::Encoding::V1) {
     271           0 :         assert(s.IsAddrV1Compatible());
     272           0 :     }
     273           0 : }
     274           4 : FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
     275             :     CMessageHeader mh;
     276             :     DeserializeFromFuzzingInput(buffer, mh);
     277             :     (void)mh.IsCommandValid();
     278             : })
     279           4 : FUZZ_TARGET(address_deserialize, .init = initialize_deserialize)
     280             : {
     281           0 :     FuzzedDataProvider fdp{buffer.data(), buffer.size()};
     282           0 :     const auto ser_enc{ConsumeDeserializationParams<CAddress::SerParams>(fdp)};
     283           0 :     const auto maybe_a{ConsumeDeserializable<CAddress>(fdp, ser_enc)};
     284           0 :     if (!maybe_a) return;
     285           0 :     const CAddress& a{*maybe_a};
     286             :     // A CAddress in V1 mode will roundtrip
     287             :     // in all 4 formats (v1/v2, network/disk)
     288           0 :     if (ser_enc.enc == CNetAddr::Encoding::V1) {
     289           0 :         AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
     290           0 :         AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
     291           0 :         AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
     292           0 :         AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
     293           0 :     } else {
     294             :         // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
     295             :         // if it's V1 compatible.
     296           0 :         if (a.IsAddrV1Compatible()) {
     297           0 :             AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
     298           0 :             AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
     299           0 :         }
     300           0 :         AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
     301           0 :         AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
     302             :     }
     303           0 : }
     304           4 : FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
     305             :     CInv i;
     306             :     DeserializeFromFuzzingInput(buffer, i);
     307             : })
     308           4 : FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
     309             :     CBloomFilter bf;
     310             :     DeserializeFromFuzzingInput(buffer, bf);
     311             : })
     312           4 : FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
     313             :     CDiskBlockIndex dbi;
     314             :     DeserializeFromFuzzingInput(buffer, dbi);
     315             : })
     316           4 : FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
     317             :     CTxOut to;
     318             :     auto toc = Using<TxOutCompression>(to);
     319             :     DeserializeFromFuzzingInput(buffer, toc);
     320             : })
     321           4 : FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
     322             :     BlockTransactions bt;
     323             :     DeserializeFromFuzzingInput(buffer, bt);
     324             : })
     325           4 : FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
     326             :     BlockTransactionsRequest btr;
     327             :     DeserializeFromFuzzingInput(buffer, btr);
     328             : })
     329           4 : FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
     330             :     SnapshotMetadata snapshot_metadata;
     331             :     DeserializeFromFuzzingInput(buffer, snapshot_metadata);
     332             : })
     333           4 : FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
     334             :     uint160 u160;
     335             :     DeserializeFromFuzzingInput(buffer, u160);
     336             :     AssertEqualAfterSerializeDeserialize(u160);
     337             : })
     338           4 : FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
     339             :     uint256 u256;
     340             :     DeserializeFromFuzzingInput(buffer, u256);
     341             :     AssertEqualAfterSerializeDeserialize(u256);
     342             : })
     343             : // Classes intentionally not covered in this file since their deserialization code is
     344             : // fuzzed elsewhere:
     345             : // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
     346             : // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp

Generated by: LCOV version 1.14