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