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