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 : : namespace {
42 : : const BasicTestingSetup* g_setup;
43 : : } // namespace
44 : :
45 : 37 : void initialize_deserialize()
46 : : {
47 [ + - + - : 37 : static const auto testing_setup = MakeNoLogFileContext<>();
+ - ]
48 : 37 : g_setup = testing_setup.get();
49 : 37 : }
50 : :
51 : : #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 : 3084 : struct invalid_fuzzing_input_exception : public std::exception {
63 : : };
64 : :
65 : : template <typename T, typename P>
66 : 675 : DataStream Serialize(const T& obj, const P& params)
67 : : {
68 [ + - ]: 675 : DataStream ds{};
69 [ + - ]: 675 : ds << params(obj);
70 : 675 : return ds;
71 : 0 : }
72 : :
73 : : template <typename T, typename P>
74 : 675 : T Deserialize(DataStream&& ds, const P& params)
75 : : {
76 [ + - ]: 675 : T obj;
77 [ + - ]: 675 : ds >> params(obj);
78 : 675 : return obj;
79 : 0 : }
80 : :
81 : : template <typename T, typename P>
82 : : void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj, const P& params)
83 : : {
84 : : DataStream ds{buffer};
85 : : try {
86 : : ds >> 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 : 3742 : DataStream Serialize(const T& obj)
95 : : {
96 [ + - ]: 3742 : DataStream ds{};
97 : 3742 : ds << obj;
98 : 3742 : return ds;
99 : 0 : }
100 : :
101 : : template <typename T>
102 [ + - ]: 128 : T Deserialize(DataStream ds)
103 : : {
104 [ + - ]: 128 : T obj;
105 : 128 : ds >> obj;
106 : 128 : return obj;
107 : 0 : }
108 : :
109 : : template <typename T>
110 : 6698 : void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj)
111 : : {
112 [ + + ]: 6698 : DataStream ds{buffer};
113 : : try {
114 : 3614 : ds >> obj;
115 [ - + ]: 6168 : } catch (const std::ios_base::failure&) {
116 : 3084 : throw invalid_fuzzing_input_exception();
117 : : }
118 [ + - + - : 7228 : assert(buffer.empty() || !Serialize(obj).empty());
- + - + ]
119 : 3614 : }
120 : :
121 : : template <typename T, typename P>
122 : 675 : void AssertEqualAfterSerializeDeserialize(const T& obj, const P& params)
123 : : {
124 [ + - + - : 1350 : assert(Deserialize<T>(Serialize(obj, params), params) == obj);
- + ]
125 : 675 : }
126 : : template <typename T>
127 : 128 : void AssertEqualAfterSerializeDeserialize(const T& obj)
128 : : {
129 [ + - - + ]: 278 : assert(Deserialize<T>(Serialize(obj)) == obj);
130 : 128 : }
131 : :
132 : : } // namespace
133 : :
134 [ + - + + : 685 : FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
- + ]
135 : : BlockFilter block_filter;
136 : : DeserializeFromFuzzingInput(buffer, block_filter);
137 : : })
138 [ + - ]: 601 : FUZZ_TARGET(addr_info_deserialize, .init = initialize_deserialize)
139 : : {
140 : 143 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
141 [ + + ]: 143 : (void)ConsumeDeserializable<AddrInfo>(fdp, ConsumeDeserializationParams<CAddress::SerParams>(fdp));
142 : 143 : }
143 [ + + - + ]: 519 : FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
144 : : CBlockFileInfo block_file_info;
145 : : DeserializeFromFuzzingInput(buffer, block_file_info);
146 : : })
147 [ + + - + ]: 967 : FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
148 : : CBlockHeaderAndShortTxIDs block_header_and_short_txids;
149 : : DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
150 : : })
151 [ + + + - : 482 : FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
- + ]
152 : : CFeeRate fee_rate;
153 : : DeserializeFromFuzzingInput(buffer, fee_rate);
154 : : AssertEqualAfterSerializeDeserialize(fee_rate);
155 : : })
156 [ + - + + : 590 : FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
- + ]
157 : : CMerkleBlock merkle_block;
158 : : DeserializeFromFuzzingInput(buffer, merkle_block);
159 : : })
160 [ + + + - : 485 : FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
- + ]
161 : : COutPoint out_point;
162 : : DeserializeFromFuzzingInput(buffer, out_point);
163 : : AssertEqualAfterSerializeDeserialize(out_point);
164 : : })
165 [ + - + + : 649 : FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
- + ]
166 : : CPartialMerkleTree partial_merkle_tree;
167 : : DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
168 : : })
169 [ + + + - : 519 : FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
- + ]
170 : : CPubKey pub_key;
171 : : DeserializeFromFuzzingInput(buffer, pub_key);
172 : : AssertEqualAfterSerializeDeserialize(pub_key);
173 : : })
174 [ + + - + ]: 544 : FUZZ_TARGET_DESERIALIZE(script_deserialize, {
175 : : CScript script;
176 : : DeserializeFromFuzzingInput(buffer, script);
177 : : })
178 [ + + + - : 608 : FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
- + ]
179 : : CTxIn tx_in;
180 : : DeserializeFromFuzzingInput(buffer, tx_in);
181 : : AssertEqualAfterSerializeDeserialize(tx_in);
182 : : })
183 [ + + + - : 507 : FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
- + ]
184 : : FlatFilePos flat_file_pos;
185 : : DeserializeFromFuzzingInput(buffer, flat_file_pos);
186 : : AssertEqualAfterSerializeDeserialize(flat_file_pos);
187 : : })
188 [ + + + - : 575 : FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
- + ]
189 : : KeyOriginInfo key_origin_info;
190 : : DeserializeFromFuzzingInput(buffer, key_origin_info);
191 : : AssertEqualAfterSerializeDeserialize(key_origin_info);
192 : : })
193 [ + + - + ]: 4848 : FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
194 : : PartiallySignedTransaction partially_signed_transaction;
195 : : DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
196 : : })
197 [ + + - + ]: 873 : FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
198 : : PrefilledTransaction prefilled_transaction;
199 : : DeserializeFromFuzzingInput(buffer, prefilled_transaction);
200 : : })
201 [ + + - + ]: 3276 : FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
202 : : PSBTInput psbt_input;
203 : : DeserializeFromFuzzingInput(buffer, psbt_input);
204 : : })
205 [ + + - + ]: 1636 : FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
206 : : PSBTOutput psbt_output;
207 : : DeserializeFromFuzzingInput(buffer, psbt_output);
208 : : })
209 [ + + - + ]: 942 : FUZZ_TARGET_DESERIALIZE(block_deserialize, {
210 : : CBlock block;
211 : : DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
212 : : })
213 [ + + - + ]: 578 : FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
214 : : CBlockLocator bl;
215 : : DeserializeFromFuzzingInput(buffer, bl);
216 : : })
217 [ + + + - : 977 : FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
- + ]
218 : : CBlock block;
219 : : DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
220 : : bool mutated;
221 : : BlockMerkleRoot(block, &mutated);
222 : : })
223 [ + + - + ]: 480 : FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
224 : : CBlockHeader bh;
225 : : DeserializeFromFuzzingInput(buffer, bh);
226 : : })
227 [ + + - + ]: 969 : FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
228 : : CTxUndo tu;
229 : : DeserializeFromFuzzingInput(buffer, tu);
230 : : })
231 [ + + - + ]: 994 : FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
232 : : CBlockUndo bu;
233 : : DeserializeFromFuzzingInput(buffer, bu);
234 : : })
235 [ + + - + ]: 699 : FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
236 : : Coin coin;
237 : : DeserializeFromFuzzingInput(buffer, coin);
238 : : })
239 [ + - ]: 598 : FUZZ_TARGET(netaddr_deserialize, .init = initialize_deserialize)
240 : : {
241 : 140 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
242 : 140 : const auto maybe_na{ConsumeDeserializable<CNetAddr>(fdp, ConsumeDeserializationParams<CNetAddr::SerParams>(fdp))};
243 [ + + ]: 140 : if (!maybe_na) return;
244 [ + - ]: 99 : const CNetAddr& na{*maybe_na};
245 [ + - + + ]: 99 : if (na.IsAddrV1Compatible()) {
246 [ + - ]: 93 : AssertEqualAfterSerializeDeserialize(na, CNetAddr::V1);
247 : : }
248 [ + - ]: 99 : AssertEqualAfterSerializeDeserialize(na, CNetAddr::V2);
249 : 140 : }
250 [ + - ]: 596 : FUZZ_TARGET(service_deserialize, .init = initialize_deserialize)
251 : : {
252 : 138 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
253 : 138 : const auto ser_params{ConsumeDeserializationParams<CNetAddr::SerParams>(fdp)};
254 : 138 : const auto maybe_s{ConsumeDeserializable<CService>(fdp, ser_params)};
255 [ + + ]: 138 : if (!maybe_s) return;
256 [ + - ]: 80 : const CService& s{*maybe_s};
257 [ + - + + ]: 80 : if (s.IsAddrV1Compatible()) {
258 [ + - ]: 73 : AssertEqualAfterSerializeDeserialize(s, CNetAddr::V1);
259 : : }
260 [ + - ]: 80 : AssertEqualAfterSerializeDeserialize(s, CNetAddr::V2);
261 [ + + ]: 80 : if (ser_params.enc == CNetAddr::Encoding::V1) {
262 [ + - - + ]: 34 : assert(s.IsAddrV1Compatible());
263 : : }
264 : 138 : }
265 [ + + + - : 542 : FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
- + ]
266 : : CMessageHeader mh;
267 : : DeserializeFromFuzzingInput(buffer, mh);
268 : : (void)mh.IsMessageTypeValid();
269 : : })
270 [ + - ]: 657 : FUZZ_TARGET(address_deserialize, .init = initialize_deserialize)
271 : : {
272 : 199 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
273 : 199 : const auto ser_enc{ConsumeDeserializationParams<CAddress::SerParams>(fdp)};
274 : 199 : const auto maybe_a{ConsumeDeserializable<CAddress>(fdp, ser_enc)};
275 [ + + ]: 199 : if (!maybe_a) return;
276 [ + + ]: 87 : const CAddress& a{*maybe_a};
277 : : // A CAddress in V1 mode will roundtrip
278 : : // in all 4 formats (v1/v2, network/disk)
279 [ + + ]: 87 : if (ser_enc.enc == CNetAddr::Encoding::V1) {
280 [ + - ]: 32 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
281 [ + - ]: 32 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
282 [ + - ]: 32 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
283 [ + - ]: 32 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
284 : : } else {
285 : : // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
286 : : // if it's V1 compatible.
287 [ + - + + ]: 55 : if (a.IsAddrV1Compatible()) {
288 [ + - ]: 46 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
289 [ + - ]: 46 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
290 : : }
291 [ + - ]: 55 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
292 [ + - ]: 55 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
293 : : }
294 : 199 : }
295 [ + - + + : 481 : FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
- + ]
296 : : CInv i;
297 : : DeserializeFromFuzzingInput(buffer, i);
298 : : })
299 [ + + - + ]: 554 : FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
300 : : CBloomFilter bf;
301 : : DeserializeFromFuzzingInput(buffer, bf);
302 : : })
303 [ + + - + ]: 532 : FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
304 : : CDiskBlockIndex dbi;
305 : : DeserializeFromFuzzingInput(buffer, dbi);
306 : : })
307 [ + + - + ]: 668 : FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
308 : : CTxOut to;
309 : : auto toc = Using<TxOutCompression>(to);
310 : : DeserializeFromFuzzingInput(buffer, toc);
311 : : })
312 [ + + - + ]: 990 : FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
313 : : BlockTransactions bt;
314 : : DeserializeFromFuzzingInput(buffer, bt);
315 : : })
316 [ + + - + ]: 599 : FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
317 : : BlockTransactionsRequest btr;
318 : : DeserializeFromFuzzingInput(buffer, btr);
319 : : })
320 [ + - + - : 521 : FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
+ + - + ]
321 : : auto msg_start = Params().MessageStart();
322 : : SnapshotMetadata snapshot_metadata{msg_start};
323 : : DeserializeFromFuzzingInput(buffer, snapshot_metadata);
324 : : })
325 [ + + + - : 478 : FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
- + ]
326 : : uint160 u160;
327 : : DeserializeFromFuzzingInput(buffer, u160);
328 : : AssertEqualAfterSerializeDeserialize(u160);
329 : : })
330 [ + + + - : 477 : FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
- + ]
331 : : uint256 u256;
332 : : DeserializeFromFuzzingInput(buffer, u256);
333 : : AssertEqualAfterSerializeDeserialize(u256);
334 : : })
335 : : // Classes intentionally not covered in this file since their deserialization code is
336 : : // fuzzed elsewhere:
337 : : // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
338 : : // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
|