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