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 [ + - + - : 74 : 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 : 4937 : struct invalid_fuzzing_input_exception : public std::exception {
58 : : };
59 : :
60 : : template <typename T, typename P>
61 : 712 : T Deserialize(DataStream&& ds, const P& params)
62 : : {
63 [ + - ]: 712 : T obj;
64 [ + - ]: 712 : ds >> params(obj);
65 : 712 : return obj;
66 : 0 : }
67 : :
68 : : template <typename T>
69 : 5594 : DataStream Serialize(const T& obj)
70 : : {
71 [ + - ]: 5594 : DataStream ds{};
72 : 5594 : ds << obj;
73 : 5594 : return ds;
74 : 0 : }
75 : :
76 : : template <typename T>
77 [ + - ]: 165 : T Deserialize(DataStream ds)
78 : : {
79 [ + - ][ + - ]: 165 : T obj;
80 : 165 : ds >> obj;
81 : 165 : return obj;
82 : 0 : }
83 : :
84 : : template <typename T>
85 : 6582 : void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj)
86 : : {
87 : : try {
88 [ + + ]: 6582 : SpanReader{buffer} >> obj;
89 [ - + ]: 6122 : } catch (const std::ios_base::failure&) {
90 : 3061 : throw invalid_fuzzing_input_exception();
91 : : }
92 [ + - - + : 7042 : assert(buffer.empty() || !Serialize(obj).empty());
- + ]
93 : 3521 : }
94 : :
95 : : template <typename T>
96 : 3072 : T DeserializeConstructFromFuzzingInput(FuzzBufferType buffer)
97 : : {
98 : : try {
99 : 3072 : SpanReader reader{buffer};
100 [ + + ]: 3072 : T obj(deserialize, reader);
101 [ + - + - : 2392 : assert(buffer.empty() || !Serialize(obj).empty());
- + - + ]
102 : 1196 : return obj;
103 [ - + ]: 3752 : } catch (const std::ios_base::failure&) {
104 : 1876 : throw invalid_fuzzing_input_exception();
105 : : }
106 : : }
107 : :
108 : : template <typename T, typename P>
109 : 712 : void AssertEqualAfterSerializeDeserialize(const T& obj, const P& params)
110 : : {
111 [ + - + - : 1424 : assert(Deserialize<T>(Serialize(params(obj)), params) == obj);
- + ]
112 : 712 : }
113 : : template <typename T>
114 : 165 : void AssertEqualAfterSerializeDeserialize(const T& obj)
115 : : {
116 [ + - ][ + - ]: 296 : assert(Deserialize<T>(Serialize(obj)) == obj);
[ + - - + ]
[ + - - + ]
[ + - - + ]
117 : 165 : }
118 : :
119 : : } // namespace
120 : :
121 [ + - ][ + - : 761 : FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
+ + - + ]
122 : : BlockFilter block_filter;
123 : : DeserializeFromFuzzingInput(buffer, block_filter);
124 : : })
125 [ + - ]: 690 : FUZZ_TARGET(addr_info_deserialize, .init = initialize_deserialize)
126 : : {
127 : 216 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
128 [ + + ]: 216 : (void)ConsumeDeserializable<AddrInfo>(fdp, ConsumeDeserializationParams<CAddress::SerParams>(fdp));
129 : 216 : }
130 [ + - ]: 550 : FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
[ + + - + ]
131 : : CBlockFileInfo block_file_info;
132 : : DeserializeFromFuzzingInput(buffer, block_file_info);
133 : : })
134 [ + - ]: 1311 : FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
[ + + - + ]
135 : : CBlockHeaderAndShortTxIDs block_header_and_short_txids;
136 : : DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
137 : : })
138 [ + - ][ + + : 492 : FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
+ - - + ]
139 : : CFeeRate fee_rate;
140 : : DeserializeFromFuzzingInput(buffer, fee_rate);
141 : : AssertEqualAfterSerializeDeserialize(fee_rate);
142 : : })
143 [ + - ][ + - : 653 : FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
+ + - + ]
144 : : CMerkleBlock merkle_block;
145 : : DeserializeFromFuzzingInput(buffer, merkle_block);
146 : : })
147 [ + - ][ + + : 492 : FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
+ - - + ]
148 : : COutPoint out_point;
149 : : DeserializeFromFuzzingInput(buffer, out_point);
150 : : AssertEqualAfterSerializeDeserialize(out_point);
151 : : })
152 [ + - ][ + - : 741 : FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
+ + - + ]
153 : : CPartialMerkleTree partial_merkle_tree;
154 : : DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
155 : : })
156 [ + - ][ + + : 552 : FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
+ - - + ]
157 : : CPubKey pub_key;
158 : : DeserializeFromFuzzingInput(buffer, pub_key);
159 : : AssertEqualAfterSerializeDeserialize(pub_key);
160 : : })
161 [ + - ]: 622 : FUZZ_TARGET_DESERIALIZE(script_deserialize, {
[ + + - + ]
162 : : CScript script;
163 : : DeserializeFromFuzzingInput(buffer, script);
164 : : })
165 [ + - ][ + + : 692 : FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
+ - - + ]
166 : : CTxIn tx_in;
167 : : DeserializeFromFuzzingInput(buffer, tx_in);
168 : : AssertEqualAfterSerializeDeserialize(tx_in);
169 : : })
170 [ + - ][ + + : 522 : FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
+ - - + ]
171 : : FlatFilePos flat_file_pos;
172 : : DeserializeFromFuzzingInput(buffer, flat_file_pos);
173 : : AssertEqualAfterSerializeDeserialize(flat_file_pos);
174 : : })
175 [ + - ][ + + : 634 : FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
+ - - + ]
176 : : KeyOriginInfo key_origin_info;
177 : : DeserializeFromFuzzingInput(buffer, key_origin_info);
178 : : AssertEqualAfterSerializeDeserialize(key_origin_info);
179 : : })
180 [ + - ]: 5422 : FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
[ + + - + ]
181 : : PartiallySignedTransaction partially_signed_transaction = DeserializeConstructFromFuzzingInput<PartiallySignedTransaction>(buffer);
182 : : })
183 [ + - ]: 1029 : FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
[ + + - + ]
184 : : PrefilledTransaction prefilled_transaction;
185 : : DeserializeFromFuzzingInput(buffer, prefilled_transaction);
186 : : })
187 [ + - ]: 4649 : FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
[ + + - + ]
188 : : PSBTInput psbt_input(0, Txid{}, 0);
189 : : DeserializeFromFuzzingInput(buffer, psbt_input);
190 : : })
191 [ + - ]: 2527 : FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
[ + + - + ]
192 : : PSBTOutput psbt_output(0, 0, CScript());
193 : : DeserializeFromFuzzingInput(buffer, psbt_output);
194 : : })
195 [ + - ]: 1199 : FUZZ_TARGET_DESERIALIZE(block_deserialize, {
[ + + - + ]
196 : : CBlock block;
197 : : DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
198 : : })
199 [ + - ]: 631 : FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
[ + + - + ]
200 : : CBlockLocator bl;
201 : : DeserializeFromFuzzingInput(buffer, bl);
202 : : })
203 [ + - ][ + + : 1268 : FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
+ - - + ]
204 : : CBlock block;
205 : : DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
206 : : bool mutated;
207 : : BlockMerkleRoot(block, &mutated);
208 : : })
209 [ + - ]: 505 : FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
[ + + - + ]
210 : : CBlockHeader bh;
211 : : DeserializeFromFuzzingInput(buffer, bh);
212 : : })
213 [ + - ]: 1233 : FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
[ + + - + ]
214 : : CTxUndo tu;
215 : : DeserializeFromFuzzingInput(buffer, tu);
216 : : })
217 [ + - ]: 1379 : FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
[ + + - + ]
218 : : CBlockUndo bu;
219 : : DeserializeFromFuzzingInput(buffer, bu);
220 : : })
221 [ + - ]: 860 : FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
[ + + - + ]
222 : : Coin coin;
223 : : DeserializeFromFuzzingInput(buffer, coin);
224 : : })
225 [ + - ]: 637 : FUZZ_TARGET(netaddr_deserialize, .init = initialize_deserialize)
226 : : {
227 : 163 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
228 : 163 : const auto maybe_na{ConsumeDeserializable<CNetAddr>(fdp, ConsumeDeserializationParams<CNetAddr::SerParams>(fdp))};
229 [ + + ]: 163 : if (!maybe_na) return;
230 [ + - ]: 96 : const CNetAddr& na{*maybe_na};
231 [ + - + + ]: 96 : if (na.IsAddrV1Compatible()) {
232 [ + - ]: 89 : AssertEqualAfterSerializeDeserialize(na, CNetAddr::V1);
233 : : }
234 [ + - ]: 96 : AssertEqualAfterSerializeDeserialize(na, CNetAddr::V2);
235 : 163 : }
236 [ + - ]: 660 : FUZZ_TARGET(service_deserialize, .init = initialize_deserialize)
237 : : {
238 : 186 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
239 : 186 : const auto ser_params{ConsumeDeserializationParams<CNetAddr::SerParams>(fdp)};
240 : 186 : const auto maybe_s{ConsumeDeserializable<CService>(fdp, ser_params)};
241 [ + + ]: 186 : if (!maybe_s) return;
242 [ + - ]: 100 : const CService& s{*maybe_s};
243 [ + - + + ]: 100 : if (s.IsAddrV1Compatible()) {
244 [ + - ]: 89 : AssertEqualAfterSerializeDeserialize(s, CNetAddr::V1);
245 : : }
246 [ + - ]: 100 : AssertEqualAfterSerializeDeserialize(s, CNetAddr::V2);
247 [ + + ]: 100 : if (ser_params.enc == CNetAddr::Encoding::V1) {
248 [ + - - + ]: 22 : assert(s.IsAddrV1Compatible());
249 : : }
250 : 186 : }
251 [ + - ][ + + : 607 : FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
+ - - + ]
252 : : CMessageHeader mh;
253 : : DeserializeFromFuzzingInput(buffer, mh);
254 : : (void)mh.IsMessageTypeValid();
255 : : })
256 [ + - ]: 700 : FUZZ_TARGET(address_deserialize, .init = initialize_deserialize)
257 : : {
258 : 226 : FuzzedDataProvider fdp{buffer.data(), buffer.size()};
259 : 226 : const auto ser_enc{ConsumeDeserializationParams<CAddress::SerParams>(fdp)};
260 : 226 : const auto maybe_a{ConsumeDeserializable<CAddress>(fdp, ser_enc)};
261 [ + + ]: 226 : if (!maybe_a) return;
262 [ + + ]: 90 : const CAddress& a{*maybe_a};
263 : : // A CAddress in V1 mode will roundtrip
264 : : // in all 4 formats (v1/v2, network/disk)
265 [ + + ]: 90 : if (ser_enc.enc == CNetAddr::Encoding::V1) {
266 [ + - ]: 10 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
267 [ + - ]: 10 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
268 [ + - ]: 10 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
269 [ + - ]: 10 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
270 : : } else {
271 : : // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
272 : : // if it's V1 compatible.
273 [ + - + + ]: 80 : if (a.IsAddrV1Compatible()) {
274 [ + - ]: 69 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
275 [ + - ]: 69 : AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
276 : : }
277 [ + - ]: 80 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
278 [ + - ]: 80 : AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
279 : : }
280 : 226 : }
281 [ + - ][ + - : 494 : FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
+ + - + ]
282 : : CInv i;
283 : : DeserializeFromFuzzingInput(buffer, i);
284 : : })
285 [ + - ]: 633 : FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
[ + + - + ]
286 : : CBloomFilter bf;
287 : : DeserializeFromFuzzingInput(buffer, bf);
288 : : })
289 [ + - ]: 569 : FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
[ + + - + ]
290 : : CDiskBlockIndex dbi;
291 : : DeserializeFromFuzzingInput(buffer, dbi);
292 : : })
293 [ + - ]: 829 : FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
[ + + - + ]
294 : : CTxOut to;
295 : : auto toc = Using<TxOutCompression>(to);
296 : : DeserializeFromFuzzingInput(buffer, toc);
297 : : })
298 [ + - ]: 1260 : FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
[ + + - + ]
299 : : BlockTransactions bt;
300 : : DeserializeFromFuzzingInput(buffer, bt);
301 : : })
302 [ + - ]: 682 : FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
[ + + - + ]
303 : : BlockTransactionsRequest btr;
304 : : DeserializeFromFuzzingInput(buffer, btr);
305 : : })
306 [ + - ][ + - : 545 : FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
+ - + + -
+ ]
307 : : auto msg_start = Params().MessageStart();
308 : : SnapshotMetadata snapshot_metadata{msg_start};
309 : : DeserializeFromFuzzingInput(buffer, snapshot_metadata);
310 : : })
311 [ + - ][ + + : 486 : FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
+ - - + ]
312 : : uint160 u160;
313 : : DeserializeFromFuzzingInput(buffer, u160);
314 : : AssertEqualAfterSerializeDeserialize(u160);
315 : : })
316 [ + - ][ + + : 486 : FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
+ - - + ]
317 : : uint256 u256;
318 : : DeserializeFromFuzzingInput(buffer, u256);
319 : : AssertEqualAfterSerializeDeserialize(u256);
320 : : })
321 : : // Classes intentionally not covered in this file since their deserialization code is
322 : : // fuzzed elsewhere:
323 : : // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
324 : : // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
|