1 // Copyright (c) 2009-2019 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 <blockencodings.h>
8 #include <blockfilter.h>
9 #include <chain.h>
10 #include <coins.h>
11 #include <compressor.h>
12 #include <consensus/merkle.h>
13 #include <key.h>
14 #include <merkleblock.h>
15 #include <net.h>
16 #include <node/utxo_snapshot.h>
17 #include <primitives/block.h>
18 #include <protocol.h>
19 #include <psbt.h>
20 #include <pubkey.h>
21 #include <script/keyorigin.h>
22 #include <streams.h>
23 #include <undo.h>
24 #include <version.h>
25
26 #include <exception>
27 #include <stdexcept>
28 #include <stdint.h>
29 #include <unistd.h>
30
31 #include <vector>
32
33 #include <test/fuzz/fuzz.h>
34
initialize()35 void initialize()
36 {
37 // Fuzzers using pubkey must hold an ECCVerifyHandle.
38 static const ECCVerifyHandle verify_handle;
39 }
40
41 namespace {
42
43 struct invalid_fuzzing_input_exception : public std::exception {
44 };
45
46 template <typename T>
Serialize(const T & obj)47 CDataStream Serialize(const T& obj)
48 {
49 CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION);
50 ds << obj;
51 return ds;
52 }
53
54 template <typename T>
Deserialize(CDataStream ds)55 T Deserialize(CDataStream ds)
56 {
57 T obj;
58 ds >> obj;
59 return obj;
60 }
61
62 template <typename T>
DeserializeFromFuzzingInput(const std::vector<uint8_t> & buffer,T & obj)63 void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj)
64 {
65 CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
66 try {
67 int version;
68 ds >> version;
69 ds.SetVersion(version);
70 } catch (const std::ios_base::failure&) {
71 throw invalid_fuzzing_input_exception();
72 }
73 try {
74 ds >> obj;
75 } catch (const std::ios_base::failure&) {
76 throw invalid_fuzzing_input_exception();
77 }
78 assert(buffer.empty() || !Serialize(obj).empty());
79 }
80
81 template <typename T>
AssertEqualAfterSerializeDeserialize(const T & obj)82 void AssertEqualAfterSerializeDeserialize(const T& obj)
83 {
84 assert(Deserialize<T>(Serialize(obj)) == obj);
85 }
86
87 } // namespace
88
test_one_input(const std::vector<uint8_t> & buffer)89 void test_one_input(const std::vector<uint8_t>& buffer)
90 {
91 try {
92 #if BLOCK_FILTER_DESERIALIZE
93 BlockFilter block_filter;
94 DeserializeFromFuzzingInput(buffer, block_filter);
95 #elif ADDR_INFO_DESERIALIZE
96 CAddrInfo addr_info;
97 DeserializeFromFuzzingInput(buffer, addr_info);
98 #elif BLOCK_FILE_INFO_DESERIALIZE
99 CBlockFileInfo block_file_info;
100 DeserializeFromFuzzingInput(buffer, block_file_info);
101 #elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
102 CBlockHeaderAndShortTxIDs block_header_and_short_txids;
103 DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
104 #elif FEE_RATE_DESERIALIZE
105 CFeeRate fee_rate;
106 DeserializeFromFuzzingInput(buffer, fee_rate);
107 AssertEqualAfterSerializeDeserialize(fee_rate);
108 #elif MERKLE_BLOCK_DESERIALIZE
109 CMerkleBlock merkle_block;
110 DeserializeFromFuzzingInput(buffer, merkle_block);
111 #elif OUT_POINT_DESERIALIZE
112 COutPoint out_point;
113 DeserializeFromFuzzingInput(buffer, out_point);
114 AssertEqualAfterSerializeDeserialize(out_point);
115 #elif PARTIAL_MERKLE_TREE_DESERIALIZE
116 CPartialMerkleTree partial_merkle_tree;
117 DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
118 #elif PUB_KEY_DESERIALIZE
119 CPubKey pub_key;
120 DeserializeFromFuzzingInput(buffer, pub_key);
121 // TODO: The following equivalence should hold for CPubKey? Fix.
122 // AssertEqualAfterSerializeDeserialize(pub_key);
123 #elif SCRIPT_DESERIALIZE
124 CScript script;
125 DeserializeFromFuzzingInput(buffer, script);
126 #elif SUB_NET_DESERIALIZE
127 CSubNet sub_net;
128 DeserializeFromFuzzingInput(buffer, sub_net);
129 AssertEqualAfterSerializeDeserialize(sub_net);
130 #elif TX_IN_DESERIALIZE
131 CTxIn tx_in;
132 DeserializeFromFuzzingInput(buffer, tx_in);
133 AssertEqualAfterSerializeDeserialize(tx_in);
134 #elif FLAT_FILE_POS_DESERIALIZE
135 FlatFilePos flat_file_pos;
136 DeserializeFromFuzzingInput(buffer, flat_file_pos);
137 AssertEqualAfterSerializeDeserialize(flat_file_pos);
138 #elif KEY_ORIGIN_INFO_DESERIALIZE
139 KeyOriginInfo key_origin_info;
140 DeserializeFromFuzzingInput(buffer, key_origin_info);
141 AssertEqualAfterSerializeDeserialize(key_origin_info);
142 #elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
143 PartiallySignedTransaction partially_signed_transaction;
144 DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
145 #elif PREFILLED_TRANSACTION_DESERIALIZE
146 PrefilledTransaction prefilled_transaction;
147 DeserializeFromFuzzingInput(buffer, prefilled_transaction);
148 #elif PSBT_INPUT_DESERIALIZE
149 PSBTInput psbt_input;
150 DeserializeFromFuzzingInput(buffer, psbt_input);
151 #elif PSBT_OUTPUT_DESERIALIZE
152 PSBTOutput psbt_output;
153 DeserializeFromFuzzingInput(buffer, psbt_output);
154 #elif BLOCK_DESERIALIZE
155 CBlock block;
156 DeserializeFromFuzzingInput(buffer, block);
157 #elif BLOCKLOCATOR_DESERIALIZE
158 CBlockLocator bl;
159 DeserializeFromFuzzingInput(buffer, bl);
160 #elif BLOCKMERKLEROOT
161 CBlock block;
162 DeserializeFromFuzzingInput(buffer, block);
163 bool mutated;
164 BlockMerkleRoot(block, &mutated);
165 #elif ADDRMAN_DESERIALIZE
166 CAddrMan am;
167 DeserializeFromFuzzingInput(buffer, am);
168 #elif BLOCKHEADER_DESERIALIZE
169 CBlockHeader bh;
170 DeserializeFromFuzzingInput(buffer, bh);
171 #elif BANENTRY_DESERIALIZE
172 CBanEntry be;
173 DeserializeFromFuzzingInput(buffer, be);
174 #elif TXUNDO_DESERIALIZE
175 CTxUndo tu;
176 DeserializeFromFuzzingInput(buffer, tu);
177 #elif BLOCKUNDO_DESERIALIZE
178 CBlockUndo bu;
179 DeserializeFromFuzzingInput(buffer, bu);
180 #elif COINS_DESERIALIZE
181 Coin coin;
182 DeserializeFromFuzzingInput(buffer, coin);
183 #elif NETADDR_DESERIALIZE
184 CNetAddr na;
185 DeserializeFromFuzzingInput(buffer, na);
186 AssertEqualAfterSerializeDeserialize(na);
187 #elif SERVICE_DESERIALIZE
188 CService s;
189 DeserializeFromFuzzingInput(buffer, s);
190 AssertEqualAfterSerializeDeserialize(s);
191 #elif MESSAGEHEADER_DESERIALIZE
192 const CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
193 CMessageHeader mh(pchMessageStart);
194 DeserializeFromFuzzingInput(buffer, mh);
195 (void)mh.IsValid(pchMessageStart);
196 #elif ADDRESS_DESERIALIZE
197 CAddress a;
198 DeserializeFromFuzzingInput(buffer, a);
199 #elif INV_DESERIALIZE
200 CInv i;
201 DeserializeFromFuzzingInput(buffer, i);
202 #elif BLOOMFILTER_DESERIALIZE
203 CBloomFilter bf;
204 DeserializeFromFuzzingInput(buffer, bf);
205 #elif DISKBLOCKINDEX_DESERIALIZE
206 CDiskBlockIndex dbi;
207 DeserializeFromFuzzingInput(buffer, dbi);
208 #elif TXOUTCOMPRESSOR_DESERIALIZE
209 CTxOut to;
210 auto toc = Using<TxOutCompression>(to);
211 DeserializeFromFuzzingInput(buffer, toc);
212 #elif BLOCKTRANSACTIONS_DESERIALIZE
213 BlockTransactions bt;
214 DeserializeFromFuzzingInput(buffer, bt);
215 #elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
216 BlockTransactionsRequest btr;
217 DeserializeFromFuzzingInput(buffer, btr);
218 #elif SNAPSHOTMETADATA_DESERIALIZE
219 SnapshotMetadata snapshot_metadata;
220 DeserializeFromFuzzingInput(buffer, snapshot_metadata);
221 #elif UINT160_DESERIALIZE
222 uint160 u160;
223 DeserializeFromFuzzingInput(buffer, u160);
224 AssertEqualAfterSerializeDeserialize(u160);
225 #elif UINT256_DESERIALIZE
226 uint256 u256;
227 DeserializeFromFuzzingInput(buffer, u256);
228 AssertEqualAfterSerializeDeserialize(u256);
229 #else
230 #error Need at least one fuzz target to compile
231 #endif
232 // Classes intentionally not covered in this file since their deserialization code is
233 // fuzzed elsewhere:
234 // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
235 // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
236 } catch (const invalid_fuzzing_input_exception&) {
237 }
238 }
239