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
|