1 // Copyright (c) 2009-2019 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 <blockencodings.h>
8 #include <blockfilter.h>
9 #include <chain.h>
10 #include <coins.h>
11 #include <compressor.h>
12 #include <consensus/merkle.h>
13 #include <key.h>
14 #include <merkleblock.h>
15 #include <net.h>
16 #include <node/utxo_snapshot.h>
17 #include <primitives/block.h>
18 #include <protocol.h>
19 #include <psbt.h>
20 #include <pubkey.h>
21 #include <script/keyorigin.h>
22 #include <streams.h>
23 #include <undo.h>
24 #include <version.h>
25 
26 #include <exception>
27 #include <stdexcept>
28 #include <stdint.h>
29 #include <unistd.h>
30 
31 #include <vector>
32 
33 #include <test/fuzz/fuzz.h>
34 
initialize()35 void initialize()
36 {
37     // Fuzzers using pubkey must hold an ECCVerifyHandle.
38     static const ECCVerifyHandle verify_handle;
39 }
40 
41 namespace {
42 
43 struct invalid_fuzzing_input_exception : public std::exception {
44 };
45 
46 template <typename T>
Serialize(const T & obj)47 CDataStream Serialize(const T& obj)
48 {
49     CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION);
50     ds << obj;
51     return ds;
52 }
53 
54 template <typename T>
Deserialize(CDataStream ds)55 T Deserialize(CDataStream ds)
56 {
57     T obj;
58     ds >> obj;
59     return obj;
60 }
61 
62 template <typename T>
DeserializeFromFuzzingInput(const std::vector<uint8_t> & buffer,T & obj)63 void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj)
64 {
65     CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
66     try {
67         int version;
68         ds >> version;
69         ds.SetVersion(version);
70     } catch (const std::ios_base::failure&) {
71         throw invalid_fuzzing_input_exception();
72     }
73     try {
74         ds >> obj;
75     } catch (const std::ios_base::failure&) {
76         throw invalid_fuzzing_input_exception();
77     }
78     assert(buffer.empty() || !Serialize(obj).empty());
79 }
80 
81 template <typename T>
AssertEqualAfterSerializeDeserialize(const T & obj)82 void AssertEqualAfterSerializeDeserialize(const T& obj)
83 {
84     assert(Deserialize<T>(Serialize(obj)) == obj);
85 }
86 
87 } // namespace
88 
test_one_input(const std::vector<uint8_t> & buffer)89 void test_one_input(const std::vector<uint8_t>& buffer)
90 {
91     try {
92 #if BLOCK_FILTER_DESERIALIZE
93         BlockFilter block_filter;
94         DeserializeFromFuzzingInput(buffer, block_filter);
95 #elif ADDR_INFO_DESERIALIZE
96         CAddrInfo addr_info;
97         DeserializeFromFuzzingInput(buffer, addr_info);
98 #elif BLOCK_FILE_INFO_DESERIALIZE
99         CBlockFileInfo block_file_info;
100         DeserializeFromFuzzingInput(buffer, block_file_info);
101 #elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
102         CBlockHeaderAndShortTxIDs block_header_and_short_txids;
103         DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
104 #elif FEE_RATE_DESERIALIZE
105         CFeeRate fee_rate;
106         DeserializeFromFuzzingInput(buffer, fee_rate);
107         AssertEqualAfterSerializeDeserialize(fee_rate);
108 #elif MERKLE_BLOCK_DESERIALIZE
109         CMerkleBlock merkle_block;
110         DeserializeFromFuzzingInput(buffer, merkle_block);
111 #elif OUT_POINT_DESERIALIZE
112         COutPoint out_point;
113         DeserializeFromFuzzingInput(buffer, out_point);
114         AssertEqualAfterSerializeDeserialize(out_point);
115 #elif PARTIAL_MERKLE_TREE_DESERIALIZE
116         CPartialMerkleTree partial_merkle_tree;
117         DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
118 #elif PUB_KEY_DESERIALIZE
119         CPubKey pub_key;
120         DeserializeFromFuzzingInput(buffer, pub_key);
121         // TODO: The following equivalence should hold for CPubKey? Fix.
122         // AssertEqualAfterSerializeDeserialize(pub_key);
123 #elif SCRIPT_DESERIALIZE
124         CScript script;
125         DeserializeFromFuzzingInput(buffer, script);
126 #elif SUB_NET_DESERIALIZE
127         CSubNet sub_net;
128         DeserializeFromFuzzingInput(buffer, sub_net);
129         AssertEqualAfterSerializeDeserialize(sub_net);
130 #elif TX_IN_DESERIALIZE
131         CTxIn tx_in;
132         DeserializeFromFuzzingInput(buffer, tx_in);
133         AssertEqualAfterSerializeDeserialize(tx_in);
134 #elif FLAT_FILE_POS_DESERIALIZE
135         FlatFilePos flat_file_pos;
136         DeserializeFromFuzzingInput(buffer, flat_file_pos);
137         AssertEqualAfterSerializeDeserialize(flat_file_pos);
138 #elif KEY_ORIGIN_INFO_DESERIALIZE
139         KeyOriginInfo key_origin_info;
140         DeserializeFromFuzzingInput(buffer, key_origin_info);
141         AssertEqualAfterSerializeDeserialize(key_origin_info);
142 #elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
143         PartiallySignedTransaction partially_signed_transaction;
144         DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
145 #elif PREFILLED_TRANSACTION_DESERIALIZE
146         PrefilledTransaction prefilled_transaction;
147         DeserializeFromFuzzingInput(buffer, prefilled_transaction);
148 #elif PSBT_INPUT_DESERIALIZE
149         PSBTInput psbt_input;
150         DeserializeFromFuzzingInput(buffer, psbt_input);
151 #elif PSBT_OUTPUT_DESERIALIZE
152         PSBTOutput psbt_output;
153         DeserializeFromFuzzingInput(buffer, psbt_output);
154 #elif BLOCK_DESERIALIZE
155         CBlock block;
156         DeserializeFromFuzzingInput(buffer, block);
157 #elif BLOCKLOCATOR_DESERIALIZE
158         CBlockLocator bl;
159         DeserializeFromFuzzingInput(buffer, bl);
160 #elif BLOCKMERKLEROOT
161         CBlock block;
162         DeserializeFromFuzzingInput(buffer, block);
163         bool mutated;
164         BlockMerkleRoot(block, &mutated);
165 #elif ADDRMAN_DESERIALIZE
166         CAddrMan am;
167         DeserializeFromFuzzingInput(buffer, am);
168 #elif BLOCKHEADER_DESERIALIZE
169         CBlockHeader bh;
170         DeserializeFromFuzzingInput(buffer, bh);
171 #elif BANENTRY_DESERIALIZE
172         CBanEntry be;
173         DeserializeFromFuzzingInput(buffer, be);
174 #elif TXUNDO_DESERIALIZE
175         CTxUndo tu;
176         DeserializeFromFuzzingInput(buffer, tu);
177 #elif BLOCKUNDO_DESERIALIZE
178         CBlockUndo bu;
179         DeserializeFromFuzzingInput(buffer, bu);
180 #elif COINS_DESERIALIZE
181         Coin coin;
182         DeserializeFromFuzzingInput(buffer, coin);
183 #elif NETADDR_DESERIALIZE
184         CNetAddr na;
185         DeserializeFromFuzzingInput(buffer, na);
186         AssertEqualAfterSerializeDeserialize(na);
187 #elif SERVICE_DESERIALIZE
188         CService s;
189         DeserializeFromFuzzingInput(buffer, s);
190         AssertEqualAfterSerializeDeserialize(s);
191 #elif MESSAGEHEADER_DESERIALIZE
192         const CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
193         CMessageHeader mh(pchMessageStart);
194         DeserializeFromFuzzingInput(buffer, mh);
195         (void)mh.IsValid(pchMessageStart);
196 #elif ADDRESS_DESERIALIZE
197         CAddress a;
198         DeserializeFromFuzzingInput(buffer, a);
199 #elif INV_DESERIALIZE
200         CInv i;
201         DeserializeFromFuzzingInput(buffer, i);
202 #elif BLOOMFILTER_DESERIALIZE
203         CBloomFilter bf;
204         DeserializeFromFuzzingInput(buffer, bf);
205 #elif DISKBLOCKINDEX_DESERIALIZE
206         CDiskBlockIndex dbi;
207         DeserializeFromFuzzingInput(buffer, dbi);
208 #elif TXOUTCOMPRESSOR_DESERIALIZE
209         CTxOut to;
210         auto toc = Using<TxOutCompression>(to);
211         DeserializeFromFuzzingInput(buffer, toc);
212 #elif BLOCKTRANSACTIONS_DESERIALIZE
213         BlockTransactions bt;
214         DeserializeFromFuzzingInput(buffer, bt);
215 #elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
216         BlockTransactionsRequest btr;
217         DeserializeFromFuzzingInput(buffer, btr);
218 #elif SNAPSHOTMETADATA_DESERIALIZE
219         SnapshotMetadata snapshot_metadata;
220         DeserializeFromFuzzingInput(buffer, snapshot_metadata);
221 #elif UINT160_DESERIALIZE
222         uint160 u160;
223         DeserializeFromFuzzingInput(buffer, u160);
224         AssertEqualAfterSerializeDeserialize(u160);
225 #elif UINT256_DESERIALIZE
226         uint256 u256;
227         DeserializeFromFuzzingInput(buffer, u256);
228         AssertEqualAfterSerializeDeserialize(u256);
229 #else
230 #error Need at least one fuzz target to compile
231 #endif
232         // Classes intentionally not covered in this file since their deserialization code is
233         // fuzzed elsewhere:
234         // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
235         // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
236     } catch (const invalid_fuzzing_input_exception&) {
237     }
238 }
239