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