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 : : #include <util/check.h>
33 : :
34 : : #include <cstdint>
35 : : #include <exception>
36 : : #include <optional>
37 : : #include <stdexcept>
38 : :
39 : : using kernel::CBlockFileInfo;
40 : : using node::SnapshotMetadata;
41 : :
42 : 37 : void initialize_deserialize()
43 : : {
44 [ + - + - : 37 : static const auto testing_setup = MakeNoLogFileContext<>();
+ - ]
45 : 37 : }
46 : :
47 : : #define FUZZ_TARGET_DESERIALIZE(name, code) \
48 : : FUZZ_TARGET(name, .init = initialize_deserialize) \
49 : : { \
50 : : try { \
51 : : code \
52 : : } catch (const invalid_fuzzing_input_exception&) { \
53 : : } \
54 : : }
55 : :
56 : : namespace {
57 : :
58 : 3369 : struct invalid_fuzzing_input_exception : public std::exception {
59 : : };
60 : :
61 : : template <typename T, typename P>
62 : 441 : T Deserialize(DataStream&& ds, const P& params)
63 : : {
64 [ + - ]: 441 : T obj;
65 [ + - ]: 441 : ds >> params(obj);
66 : 441 : return obj;
67 : 0 : }
68 : :
69 : : template <typename T>
70 : 3909 : DataStream Serialize(const T& obj)
71 : : {
72 [ + - ]: 3909 : DataStream ds{};
73 : 3909 : ds << obj;
74 : 3909 : return ds;
75 : 0 : }
76 : :
77 : : template <typename T>
78 [ + - ]: 111 : T Deserialize(DataStream ds)
79 : : {
80 [ + - ][ + - ]: 111 : T obj;
81 : 111 : ds >> obj;
82 : 111 : return obj;
83 : 0 : }
84 : :
85 : : template <typename T>
86 : 4484 : void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj)
87 : : {
88 : : try {
89 [ + + ]: 4484 : SpanReader{buffer} >> obj;
90 [ - + ]: 4084 : } catch (const std::ios_base::failure&) {
91 : 2042 : throw invalid_fuzzing_input_exception();
92 : : }
93 [ + - - + : 4884 : assert(buffer.empty() || !Serialize(obj).empty());
- + ]
94 : 2442 : }
95 : :
96 : : template <typename T>
97 : 2242 : T DeserializeConstructFromFuzzingInput(FuzzBufferType buffer)
98 : : {
99 : : try {
100 : 2242 : SpanReader reader{buffer};
101 [ + + ]: 2242 : T obj(deserialize, reader);
102 [ + - + - : 1830 : assert(buffer.empty() || !Serialize(obj).empty());
- + - + ]
103 : 915 : return obj;
104 [ - + ]: 2654 : } catch (const std::ios_base::failure&) {
105 : 1327 : throw invalid_fuzzing_input_exception();
106 : : }
107 : : }
108 : :
109 : : template <typename T, typename P>
110 : 441 : void AssertEqualAfterSerializeDeserialize(const T& obj, const P& params)
111 : : {
112 [ + - + - : 775 : assert(Deserialize<T>(Serialize(params(obj)), params) == obj);
- + ]
113 : 441 : }
114 : : template <typename T>
115 : 111 : void AssertEqualAfterSerializeDeserialize(const T& obj)
116 : : {
117 [ + - ][ + - ]: 201 : assert(Deserialize<T>(Serialize(obj)) == obj);
[ + - - + ]
[ + - - + ]
[ + - - + ]
118 : 111 : }
119 : :
120 : : } // namespace
121 : :
122 [ + - ][ + - : 668 : FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
+ + - + ]
123 : : BlockFilter block_filter;
124 : : DeserializeFromFuzzingInput(buffer, block_filter);
125 : : })
126 [ + - ]: 630 : FUZZ_TARGET(addr_info_deserialize, .init = initialize_deserialize)
127 : : {
128 : 154 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
129 [ + + ]: 154 : (void)ConsumeDeserializable<AddrInfo>(fdp, ConsumeDeserializationParams<CAddress::SerParams>(fdp));
130 : 154 : }
131 [ + - ]: 531 : FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
[ + + - + ]
132 : : CBlockFileInfo block_file_info;
133 : : DeserializeFromFuzzingInput(buffer, block_file_info);
134 : : })
135 [ + - ]: 1018 : FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
[ + + - + ]
136 : : CBlockHeaderAndShortTxIDs block_header_and_short_txids;
137 : : DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
138 : : })
139 [ + - ][ + + : 486 : FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
+ - - + ]
140 : : CFeeRate fee_rate;
141 : : DeserializeFromFuzzingInput(buffer, fee_rate);
142 : : AssertEqualAfterSerializeDeserialize(fee_rate);
143 : : })
144 [ + - ][ + - : 599 : FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
+ + - + ]
145 : : CMerkleBlock merkle_block;
146 : : DeserializeFromFuzzingInput(buffer, merkle_block);
147 : : })
148 [ + - ][ + + : 486 : FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
+ - - + ]
149 : : COutPoint out_point;
150 : : DeserializeFromFuzzingInput(buffer, out_point);
151 : : AssertEqualAfterSerializeDeserialize(out_point);
152 : : })
153 [ + - ][ + - : 674 : FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
+ + - + ]
154 : : CPartialMerkleTree partial_merkle_tree;
155 : : DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
156 : : })
157 [ + - ][ + + : 525 : FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
+ - - + ]
158 : : CPubKey pub_key;
159 : : DeserializeFromFuzzingInput(buffer, pub_key);
160 : : AssertEqualAfterSerializeDeserialize(pub_key);
161 : : })
162 [ + - ]: 572 : FUZZ_TARGET_DESERIALIZE(script_deserialize, {
[ + + - + ]
163 : : CScript script;
164 : : DeserializeFromFuzzingInput(buffer, script);
165 : : })
166 [ + - ][ + + : 620 : FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
+ - - + ]
167 : : CTxIn tx_in;
168 : : DeserializeFromFuzzingInput(buffer, tx_in);
169 : : AssertEqualAfterSerializeDeserialize(tx_in);
170 : : })
171 [ + - ][ + + : 512 : FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
+ - - + ]
172 : : FlatFilePos flat_file_pos;
173 : : DeserializeFromFuzzingInput(buffer, flat_file_pos);
174 : : AssertEqualAfterSerializeDeserialize(flat_file_pos);
175 : : })
176 [ + - ][ + + : 580 : FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
+ - - + ]
177 : : KeyOriginInfo key_origin_info;
178 : : DeserializeFromFuzzingInput(buffer, key_origin_info);
179 : : AssertEqualAfterSerializeDeserialize(key_origin_info);
180 : : })
181 [ + - ]: 4045 : FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
[ + + - + ]
182 : : PartiallySignedTransaction partially_signed_transaction = DeserializeConstructFromFuzzingInput<PartiallySignedTransaction>(buffer);
183 : : })
184 [ + - ]: 888 : FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
[ + + - + ]
185 : : PrefilledTransaction prefilled_transaction;
186 : : DeserializeFromFuzzingInput(buffer, prefilled_transaction);
187 : : })
188 [ + - ]: 3343 : FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
[ + + - + ]
189 : : PSBTInput psbt_input(0, Txid{}, 0);
190 : : DeserializeFromFuzzingInput(buffer, psbt_input);
191 : : })
192 [ + - ]: 1947 : FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
[ + + - + ]
193 : : PSBTOutput psbt_output(0, 0, CScript());
194 : : DeserializeFromFuzzingInput(buffer, psbt_output);
195 : : })
196 [ + - ]: 972 : FUZZ_TARGET_DESERIALIZE(block_deserialize, {
[ + + - + ]
197 : : CBlock block;
198 : : DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
199 : : })
200 [ + - ]: 563 : FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
[ + + - + ]
201 : : CBlockLocator bl;
202 : : DeserializeFromFuzzingInput(buffer, bl);
203 : : })
204 [ + - ][ + + : 998 : FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
+ - - + ]
205 : : CBlock block;
206 : : DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
207 : : bool mutated;
208 : : BlockMerkleRoot(block, &mutated);
209 : : })
210 [ + - ]: 492 : FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
[ + + - + ]
211 : : CBlockHeader bh;
212 : : DeserializeFromFuzzingInput(buffer, bh);
213 : : })
214 [ + - ]: 979 : FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
[ + + - + ]
215 : : CTxUndo tu;
216 : : DeserializeFromFuzzingInput(buffer, tu);
217 : : })
218 [ + - ]: 1082 : FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
[ + + - + ]
219 : : CBlockUndo bu;
220 : : DeserializeFromFuzzingInput(buffer, bu);
221 : : })
222 [ + - ]: 709 : FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
[ + + - + ]
223 : : Coin coin;
224 : : DeserializeFromFuzzingInput(buffer, coin);
225 : : })
226 [ + - ]: 574 : FUZZ_TARGET(netaddr_deserialize, .init = initialize_deserialize)
227 : : {
228 : 98 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
229 : 98 : const auto maybe_na{ConsumeDeserializable<CNetAddr>(fdp, ConsumeDeserializationParams<CNetAddr::SerParams>(fdp))};
230 [ + + ]: 98 : if (!maybe_na) return;
231 [ + - ]: 56 : const CNetAddr& na{*maybe_na};
232 [ + - + + ]: 56 : if (na.IsAddrV1Compatible()) {
233 [ + - ]: 51 : AssertEqualAfterSerializeDeserialize(na, CNetAddr::V1);
234 : : }
235 [ + - ]: 56 : AssertEqualAfterSerializeDeserialize(na, CNetAddr::V2);
236 : 98 : }
237 [ + - ]: 601 : FUZZ_TARGET(service_deserialize, .init = initialize_deserialize)
238 : : {
239 : 125 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
240 : 125 : const auto ser_params{ConsumeDeserializationParams<CNetAddr::SerParams>(fdp)};
241 : 125 : const auto maybe_s{ConsumeDeserializable<CService>(fdp, ser_params)};
242 [ + + ]: 125 : if (!maybe_s) return;
243 [ + - ]: 68 : const CService& s{*maybe_s};
244 [ + - + + ]: 68 : if (s.IsAddrV1Compatible()) {
245 [ + - ]: 60 : AssertEqualAfterSerializeDeserialize(s, CNetAddr::V1);
246 : : }
247 [ + - ]: 68 : AssertEqualAfterSerializeDeserialize(s, CNetAddr::V2);
248 [ + + ]: 68 : if (ser_params.enc == CNetAddr::Encoding::V1) {
249 [ + - - + ]: 19 : assert(s.IsAddrV1Compatible());
250 : : }
251 : 125 : }
252 [ + - ][ + + : 550 : FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
+ - - + ]
253 : : CMessageHeader mh;
254 : : DeserializeFromFuzzingInput(buffer, mh);
255 : : (void)mh.IsMessageTypeValid();
256 : : })
257 [ + - ]: 622 : FUZZ_TARGET(address_deserialize, .init = initialize_deserialize)
258 : : {
259 : 146 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
260 : 146 : const auto ser_enc{ConsumeDeserializationParams<CAddress::SerParams>(fdp)};
261 : 146 : const auto maybe_a{ConsumeDeserializable<CAddress>(fdp, ser_enc)};
262 [ + + ]: 146 : if (!maybe_a) return;
263 [ + + ]: 56 : const CAddress& a{*maybe_a};
264 : : // A CAddress in V1 mode will roundtrip
265 : : // in all 4 formats (v1/v2, network/disk)
266 [ + + ]: 56 : if (ser_enc.enc == CNetAddr::Encoding::V1) {
267 [ + - ]: 11 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
268 [ + - ]: 11 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
269 [ + - ]: 11 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
270 [ + - ]: 11 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
271 : : } else {
272 : : // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
273 : : // if it's V1 compatible.
274 [ + - + + ]: 45 : if (a.IsAddrV1Compatible()) {
275 [ + - ]: 36 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
276 [ + - ]: 36 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
277 : : }
278 [ + - ]: 45 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
279 [ + - ]: 45 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
280 : : }
281 : 146 : }
282 [ + - ][ + - : 486 : FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
+ + - + ]
283 : : CInv i;
284 : : DeserializeFromFuzzingInput(buffer, i);
285 : : })
286 [ + - ]: 583 : FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
[ + + - + ]
287 : : CBloomFilter bf;
288 : : DeserializeFromFuzzingInput(buffer, bf);
289 : : })
290 [ + - ]: 537 : FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
[ + + - + ]
291 : : CDiskBlockIndex dbi;
292 : : DeserializeFromFuzzingInput(buffer, dbi);
293 : : })
294 [ + - ]: 695 : FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
[ + + - + ]
295 : : CTxOut to;
296 : : auto toc = Using<TxOutCompression>(to);
297 : : DeserializeFromFuzzingInput(buffer, toc);
298 : : })
299 [ + - ]: 984 : FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
[ + + - + ]
300 : : BlockTransactions bt;
301 : : DeserializeFromFuzzingInput(buffer, bt);
302 : : })
303 [ + - ]: 619 : FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
[ + + - + ]
304 : : BlockTransactionsRequest btr;
305 : : DeserializeFromFuzzingInput(buffer, btr);
306 : : })
307 [ + - ][ + - : 519 : FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
+ - + + -
+ ]
308 : : auto msg_start = Params().MessageStart();
309 : : SnapshotMetadata snapshot_metadata{msg_start};
310 : : DeserializeFromFuzzingInput(buffer, snapshot_metadata);
311 : : })
312 [ + - ][ + + : 482 : FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
+ - - + ]
313 : : uint160 u160;
314 : : DeserializeFromFuzzingInput(buffer, u160);
315 : : AssertEqualAfterSerializeDeserialize(u160);
316 : : })
317 [ + - ][ + + : 482 : FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
+ - - + ]
318 : : uint256 u256;
319 : : DeserializeFromFuzzingInput(buffer, u256);
320 : : AssertEqualAfterSerializeDeserialize(u256);
321 : : })
322 : : // Classes intentionally not covered in this file since their deserialization code is
323 : : // fuzzed elsewhere:
324 : : // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
325 : : // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
|