22
22
#include < undo.h>
23
23
#include < version.h>
24
24
25
+ #include < exception>
25
26
#include < stdexcept>
26
27
#include < stdint.h>
27
28
#include < unistd.h>
@@ -36,245 +37,186 @@ void initialize()
36
37
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
37
38
}
38
39
39
- void test_one_input (const std::vector<uint8_t >& buffer)
40
+ namespace {
41
+
42
+ struct invalid_fuzzing_input_exception : public std ::exception {
43
+ };
44
+
45
+ template <typename T>
46
+ CDataStream Serialize (const T& obj)
47
+ {
48
+ CDataStream ds (SER_NETWORK, INIT_PROTO_VERSION);
49
+ ds << obj;
50
+ return ds;
51
+ }
52
+
53
+ template <typename T>
54
+ T Deserialize (CDataStream ds)
55
+ {
56
+ T obj;
57
+ ds >> obj;
58
+ return obj;
59
+ }
60
+
61
+ template <typename T>
62
+ void DeserializeFromFuzzingInput (const std::vector<uint8_t >& buffer, T& obj)
40
63
{
41
64
CDataStream ds (buffer, SER_NETWORK, INIT_PROTO_VERSION);
42
65
try {
43
- int nVersion ;
44
- ds >> nVersion ;
45
- ds.SetVersion (nVersion );
66
+ int version ;
67
+ ds >> version ;
68
+ ds.SetVersion (version );
46
69
} catch (const std::ios_base::failure&) {
47
- return ;
70
+ throw invalid_fuzzing_input_exception () ;
48
71
}
49
-
50
- #if BLOCK_FILTER_DESERIALIZE
51
72
try {
52
- BlockFilter block_filter;
53
- ds >> block_filter;
73
+ ds >> obj;
54
74
} catch (const std::ios_base::failure&) {
75
+ throw invalid_fuzzing_input_exception ();
55
76
}
56
- #elif ADDR_INFO_DESERIALIZE
77
+ assert (buffer.empty () || !Serialize (obj).empty ());
78
+ }
79
+
80
+ template <typename T>
81
+ void AssertEqualAfterSerializeDeserialize (const T& obj)
82
+ {
83
+ assert (Deserialize<T>(Serialize (obj)) == obj);
84
+ }
85
+
86
+ } // namespace
87
+
88
+ void test_one_input (const std::vector<uint8_t >& buffer)
89
+ {
57
90
try {
91
+ #if BLOCK_FILTER_DESERIALIZE
92
+ BlockFilter block_filter;
93
+ DeserializeFromFuzzingInput (buffer, block_filter);
94
+ #elif ADDR_INFO_DESERIALIZE
58
95
CAddrInfo addr_info;
59
- ds >> addr_info;
60
- } catch (const std::ios_base::failure&) {
61
- }
96
+ DeserializeFromFuzzingInput (buffer, addr_info);
62
97
#elif BLOCK_FILE_INFO_DESERIALIZE
63
- try {
64
98
CBlockFileInfo block_file_info;
65
- ds >> block_file_info;
66
- } catch (const std::ios_base::failure&) {
67
- }
99
+ DeserializeFromFuzzingInput (buffer, block_file_info);
68
100
#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
69
- try {
70
101
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
71
- ds >> block_header_and_short_txids;
72
- } catch (const std::ios_base::failure&) {
73
- }
102
+ DeserializeFromFuzzingInput (buffer, block_header_and_short_txids);
74
103
#elif FEE_RATE_DESERIALIZE
75
- try {
76
104
CFeeRate fee_rate;
77
- ds >> fee_rate;
78
- } catch (const std::ios_base::failure&) {
79
- }
105
+ DeserializeFromFuzzingInput (buffer, fee_rate);
106
+ AssertEqualAfterSerializeDeserialize (fee_rate);
80
107
#elif MERKLE_BLOCK_DESERIALIZE
81
- try {
82
108
CMerkleBlock merkle_block;
83
- ds >> merkle_block;
84
- } catch (const std::ios_base::failure&) {
85
- }
109
+ DeserializeFromFuzzingInput (buffer, merkle_block);
86
110
#elif OUT_POINT_DESERIALIZE
87
- try {
88
111
COutPoint out_point;
89
- ds >> out_point;
90
- } catch (const std::ios_base::failure&) {
91
- }
112
+ DeserializeFromFuzzingInput (buffer, out_point);
113
+ AssertEqualAfterSerializeDeserialize (out_point);
92
114
#elif PARTIAL_MERKLE_TREE_DESERIALIZE
93
- try {
94
115
CPartialMerkleTree partial_merkle_tree;
95
- ds >> partial_merkle_tree;
96
- } catch (const std::ios_base::failure&) {
97
- }
116
+ DeserializeFromFuzzingInput (buffer, partial_merkle_tree);
98
117
#elif PUB_KEY_DESERIALIZE
99
- try {
100
118
CPubKey pub_key;
101
- ds >> pub_key;
102
- } catch ( const std::ios_base::failure&) {
103
- }
119
+ DeserializeFromFuzzingInput (buffer, pub_key) ;
120
+ // TODO: The following equivalence should hold for CPubKey? Fix.
121
+ // AssertEqualAfterSerializeDeserialize(pub_key);
104
122
#elif SCRIPT_DESERIALIZE
105
- try {
106
123
CScript script;
107
- ds >> script;
108
- } catch (const std::ios_base::failure&) {
109
- }
124
+ DeserializeFromFuzzingInput (buffer, script);
110
125
#elif SUB_NET_DESERIALIZE
111
- try {
112
126
CSubNet sub_net;
113
- ds >> sub_net;
114
- } catch (const std::ios_base::failure&) {
115
- }
127
+ DeserializeFromFuzzingInput (buffer, sub_net);
128
+ AssertEqualAfterSerializeDeserialize (sub_net);
116
129
#elif TX_IN_DESERIALIZE
117
- try {
118
130
CTxIn tx_in;
119
- ds >> tx_in;
120
- } catch (const std::ios_base::failure&) {
121
- }
131
+ DeserializeFromFuzzingInput (buffer, tx_in);
132
+ AssertEqualAfterSerializeDeserialize (tx_in);
122
133
#elif FLAT_FILE_POS_DESERIALIZE
123
- try {
124
134
FlatFilePos flat_file_pos;
125
- ds >> flat_file_pos;
126
- } catch (const std::ios_base::failure&) {
127
- }
135
+ DeserializeFromFuzzingInput (buffer, flat_file_pos);
136
+ AssertEqualAfterSerializeDeserialize (flat_file_pos);
128
137
#elif KEY_ORIGIN_INFO_DESERIALIZE
129
- try {
130
138
KeyOriginInfo key_origin_info;
131
- ds >> key_origin_info;
132
- } catch (const std::ios_base::failure&) {
133
- }
139
+ DeserializeFromFuzzingInput (buffer, key_origin_info);
140
+ AssertEqualAfterSerializeDeserialize (key_origin_info);
134
141
#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
135
- try {
136
142
PartiallySignedTransaction partially_signed_transaction;
137
- ds >> partially_signed_transaction;
138
- } catch (const std::ios_base::failure&) {
139
- }
143
+ DeserializeFromFuzzingInput (buffer, partially_signed_transaction);
140
144
#elif PREFILLED_TRANSACTION_DESERIALIZE
141
- try {
142
145
PrefilledTransaction prefilled_transaction;
143
- ds >> prefilled_transaction;
144
- } catch (const std::ios_base::failure&) {
145
- }
146
+ DeserializeFromFuzzingInput (buffer, prefilled_transaction);
146
147
#elif PSBT_INPUT_DESERIALIZE
147
- try {
148
148
PSBTInput psbt_input;
149
- ds >> psbt_input;
150
- } catch (const std::ios_base::failure&) {
151
- }
149
+ DeserializeFromFuzzingInput (buffer, psbt_input);
152
150
#elif PSBT_OUTPUT_DESERIALIZE
153
- try {
154
151
PSBTOutput psbt_output;
155
- ds >> psbt_output;
156
- } catch (const std::ios_base::failure&) {
157
- }
152
+ DeserializeFromFuzzingInput (buffer, psbt_output);
158
153
#elif BLOCK_DESERIALIZE
159
- try {
160
154
CBlock block;
161
- ds >> block;
162
- } catch (const std::ios_base::failure&) {
163
- }
155
+ DeserializeFromFuzzingInput (buffer, block);
164
156
#elif BLOCKLOCATOR_DESERIALIZE
165
- try {
166
157
CBlockLocator bl;
167
- ds >> bl;
168
- } catch (const std::ios_base::failure&) {
169
- }
158
+ DeserializeFromFuzzingInput (buffer, bl);
170
159
#elif BLOCKMERKLEROOT
171
- try {
172
160
CBlock block;
173
- ds >> block;
161
+ DeserializeFromFuzzingInput (buffer, block) ;
174
162
bool mutated;
175
163
BlockMerkleRoot (block, &mutated);
176
- } catch (const std::ios_base::failure&) {
177
- }
178
164
#elif ADDRMAN_DESERIALIZE
179
- try {
180
165
CAddrMan am;
181
- ds >> am;
182
- } catch (const std::ios_base::failure&) {
183
- }
166
+ DeserializeFromFuzzingInput (buffer, am);
184
167
#elif BLOCKHEADER_DESERIALIZE
185
- try {
186
168
CBlockHeader bh;
187
- ds >> bh;
188
- } catch (const std::ios_base::failure&) {
189
- }
169
+ DeserializeFromFuzzingInput (buffer, bh);
190
170
#elif BANENTRY_DESERIALIZE
191
- try {
192
171
CBanEntry be;
193
- ds >> be;
194
- } catch (const std::ios_base::failure&) {
195
- }
172
+ DeserializeFromFuzzingInput (buffer, be);
196
173
#elif TXUNDO_DESERIALIZE
197
- try {
198
174
CTxUndo tu;
199
- ds >> tu;
200
- } catch (const std::ios_base::failure&) {
201
- }
175
+ DeserializeFromFuzzingInput (buffer, tu);
202
176
#elif BLOCKUNDO_DESERIALIZE
203
- try {
204
177
CBlockUndo bu;
205
- ds >> bu;
206
- } catch (const std::ios_base::failure&) {
207
- }
178
+ DeserializeFromFuzzingInput (buffer, bu);
208
179
#elif COINS_DESERIALIZE
209
- try {
210
180
Coin coin;
211
- ds >> coin;
212
- } catch (const std::ios_base::failure&) {
213
- }
181
+ DeserializeFromFuzzingInput (buffer, coin);
214
182
#elif NETADDR_DESERIALIZE
215
- try {
216
183
CNetAddr na;
217
- ds >> na;
218
- } catch (const std::ios_base::failure&) {
219
- }
184
+ DeserializeFromFuzzingInput (buffer, na);
185
+ AssertEqualAfterSerializeDeserialize (na);
220
186
#elif SERVICE_DESERIALIZE
221
- try {
222
187
CService s;
223
- ds >> s;
224
- } catch (const std::ios_base::failure&) {
225
- }
188
+ DeserializeFromFuzzingInput (buffer, s);
189
+ AssertEqualAfterSerializeDeserialize (s);
226
190
#elif MESSAGEHEADER_DESERIALIZE
227
- CMessageHeader::MessageStartChars pchMessageStart = {0x00 , 0x00 , 0x00 , 0x00 };
228
- try {
191
+ const CMessageHeader::MessageStartChars pchMessageStart = {0x00 , 0x00 , 0x00 , 0x00 };
229
192
CMessageHeader mh (pchMessageStart);
230
- ds >> mh ;
193
+ DeserializeFromFuzzingInput (buffer, mh) ;
231
194
(void )mh.IsValid (pchMessageStart);
232
- } catch (const std::ios_base::failure&) {
233
- }
234
195
#elif ADDRESS_DESERIALIZE
235
- try {
236
196
CAddress a;
237
- ds >> a;
238
- } catch (const std::ios_base::failure&) {
239
- }
197
+ DeserializeFromFuzzingInput (buffer, a);
240
198
#elif INV_DESERIALIZE
241
- try {
242
199
CInv i;
243
- ds >> i;
244
- } catch (const std::ios_base::failure&) {
245
- }
200
+ DeserializeFromFuzzingInput (buffer, i);
246
201
#elif BLOOMFILTER_DESERIALIZE
247
- try {
248
202
CBloomFilter bf;
249
- ds >> bf;
250
- } catch (const std::ios_base::failure&) {
251
- }
203
+ DeserializeFromFuzzingInput (buffer, bf);
252
204
#elif DISKBLOCKINDEX_DESERIALIZE
253
- try {
254
205
CDiskBlockIndex dbi;
255
- ds >> dbi;
256
- } catch (const std::ios_base::failure&) {
257
- }
206
+ DeserializeFromFuzzingInput (buffer, dbi);
258
207
#elif TXOUTCOMPRESSOR_DESERIALIZE
259
- CTxOut to;
260
- CTxOutCompressor toc (to);
261
- try {
262
- ds >> toc;
263
- } catch (const std::ios_base::failure&) {
264
- }
208
+ CTxOut to;
209
+ CTxOutCompressor toc (to);
210
+ DeserializeFromFuzzingInput (buffer, toc);
265
211
#elif BLOCKTRANSACTIONS_DESERIALIZE
266
- try {
267
212
BlockTransactions bt;
268
- ds >> bt;
269
- } catch (const std::ios_base::failure&) {
270
- }
213
+ DeserializeFromFuzzingInput (buffer, bt);
271
214
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
272
- try {
273
215
BlockTransactionsRequest btr;
274
- ds >> btr;
275
- } catch (const std::ios_base::failure&) {
276
- }
216
+ DeserializeFromFuzzingInput (buffer, btr);
277
217
#else
278
218
#error Need at least one fuzz target to compile
279
219
#endif
220
+ } catch (const invalid_fuzzing_input_exception&) {
221
+ }
280
222
}
0 commit comments