Skip to content

Commit 74c6ad3

Browse files
author
MarcoFalke
committed
Merge #17225: tests: Test serialisation as part of deserialisation fuzzing. Test round-trip equality where possible.
709afb2 tests: Test serialisation as part of deserialisation fuzzing. Test round-trip equality where possible. Avoid code repetition. (practicalswift) Pull request description: Test serialisation as part of deserialisation fuzzing. Test round-trip equality where possible. ACKs for top commit: MarcoFalke: ACK 709afb2 🍲 Tree-SHA512: b8c9c24538ee516607608ac685d2e9b01eca5c15213def3fd096b16516db84bfd45516fbee43e25b28cb3481a5d4ec3f7a34713e2da35b2902081ed42b85224d
2 parents 5bf1909 + 709afb2 commit 74c6ad3

File tree

1 file changed

+98
-156
lines changed

1 file changed

+98
-156
lines changed

src/test/fuzz/deserialize.cpp

Lines changed: 98 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <undo.h>
2323
#include <version.h>
2424

25+
#include <exception>
2526
#include <stdexcept>
2627
#include <stdint.h>
2728
#include <unistd.h>
@@ -36,245 +37,186 @@ void initialize()
3637
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
3738
}
3839

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)
4063
{
4164
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
4265
try {
43-
int nVersion;
44-
ds >> nVersion;
45-
ds.SetVersion(nVersion);
66+
int version;
67+
ds >> version;
68+
ds.SetVersion(version);
4669
} catch (const std::ios_base::failure&) {
47-
return;
70+
throw invalid_fuzzing_input_exception();
4871
}
49-
50-
#if BLOCK_FILTER_DESERIALIZE
5172
try {
52-
BlockFilter block_filter;
53-
ds >> block_filter;
73+
ds >> obj;
5474
} catch (const std::ios_base::failure&) {
75+
throw invalid_fuzzing_input_exception();
5576
}
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+
{
5790
try {
91+
#if BLOCK_FILTER_DESERIALIZE
92+
BlockFilter block_filter;
93+
DeserializeFromFuzzingInput(buffer, block_filter);
94+
#elif ADDR_INFO_DESERIALIZE
5895
CAddrInfo addr_info;
59-
ds >> addr_info;
60-
} catch (const std::ios_base::failure&) {
61-
}
96+
DeserializeFromFuzzingInput(buffer, addr_info);
6297
#elif BLOCK_FILE_INFO_DESERIALIZE
63-
try {
6498
CBlockFileInfo block_file_info;
65-
ds >> block_file_info;
66-
} catch (const std::ios_base::failure&) {
67-
}
99+
DeserializeFromFuzzingInput(buffer, block_file_info);
68100
#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
69-
try {
70101
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);
74103
#elif FEE_RATE_DESERIALIZE
75-
try {
76104
CFeeRate fee_rate;
77-
ds >> fee_rate;
78-
} catch (const std::ios_base::failure&) {
79-
}
105+
DeserializeFromFuzzingInput(buffer, fee_rate);
106+
AssertEqualAfterSerializeDeserialize(fee_rate);
80107
#elif MERKLE_BLOCK_DESERIALIZE
81-
try {
82108
CMerkleBlock merkle_block;
83-
ds >> merkle_block;
84-
} catch (const std::ios_base::failure&) {
85-
}
109+
DeserializeFromFuzzingInput(buffer, merkle_block);
86110
#elif OUT_POINT_DESERIALIZE
87-
try {
88111
COutPoint out_point;
89-
ds >> out_point;
90-
} catch (const std::ios_base::failure&) {
91-
}
112+
DeserializeFromFuzzingInput(buffer, out_point);
113+
AssertEqualAfterSerializeDeserialize(out_point);
92114
#elif PARTIAL_MERKLE_TREE_DESERIALIZE
93-
try {
94115
CPartialMerkleTree partial_merkle_tree;
95-
ds >> partial_merkle_tree;
96-
} catch (const std::ios_base::failure&) {
97-
}
116+
DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
98117
#elif PUB_KEY_DESERIALIZE
99-
try {
100118
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);
104122
#elif SCRIPT_DESERIALIZE
105-
try {
106123
CScript script;
107-
ds >> script;
108-
} catch (const std::ios_base::failure&) {
109-
}
124+
DeserializeFromFuzzingInput(buffer, script);
110125
#elif SUB_NET_DESERIALIZE
111-
try {
112126
CSubNet sub_net;
113-
ds >> sub_net;
114-
} catch (const std::ios_base::failure&) {
115-
}
127+
DeserializeFromFuzzingInput(buffer, sub_net);
128+
AssertEqualAfterSerializeDeserialize(sub_net);
116129
#elif TX_IN_DESERIALIZE
117-
try {
118130
CTxIn tx_in;
119-
ds >> tx_in;
120-
} catch (const std::ios_base::failure&) {
121-
}
131+
DeserializeFromFuzzingInput(buffer, tx_in);
132+
AssertEqualAfterSerializeDeserialize(tx_in);
122133
#elif FLAT_FILE_POS_DESERIALIZE
123-
try {
124134
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);
128137
#elif KEY_ORIGIN_INFO_DESERIALIZE
129-
try {
130138
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);
134141
#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
135-
try {
136142
PartiallySignedTransaction partially_signed_transaction;
137-
ds >> partially_signed_transaction;
138-
} catch (const std::ios_base::failure&) {
139-
}
143+
DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
140144
#elif PREFILLED_TRANSACTION_DESERIALIZE
141-
try {
142145
PrefilledTransaction prefilled_transaction;
143-
ds >> prefilled_transaction;
144-
} catch (const std::ios_base::failure&) {
145-
}
146+
DeserializeFromFuzzingInput(buffer, prefilled_transaction);
146147
#elif PSBT_INPUT_DESERIALIZE
147-
try {
148148
PSBTInput psbt_input;
149-
ds >> psbt_input;
150-
} catch (const std::ios_base::failure&) {
151-
}
149+
DeserializeFromFuzzingInput(buffer, psbt_input);
152150
#elif PSBT_OUTPUT_DESERIALIZE
153-
try {
154151
PSBTOutput psbt_output;
155-
ds >> psbt_output;
156-
} catch (const std::ios_base::failure&) {
157-
}
152+
DeserializeFromFuzzingInput(buffer, psbt_output);
158153
#elif BLOCK_DESERIALIZE
159-
try {
160154
CBlock block;
161-
ds >> block;
162-
} catch (const std::ios_base::failure&) {
163-
}
155+
DeserializeFromFuzzingInput(buffer, block);
164156
#elif BLOCKLOCATOR_DESERIALIZE
165-
try {
166157
CBlockLocator bl;
167-
ds >> bl;
168-
} catch (const std::ios_base::failure&) {
169-
}
158+
DeserializeFromFuzzingInput(buffer, bl);
170159
#elif BLOCKMERKLEROOT
171-
try {
172160
CBlock block;
173-
ds >> block;
161+
DeserializeFromFuzzingInput(buffer, block);
174162
bool mutated;
175163
BlockMerkleRoot(block, &mutated);
176-
} catch (const std::ios_base::failure&) {
177-
}
178164
#elif ADDRMAN_DESERIALIZE
179-
try {
180165
CAddrMan am;
181-
ds >> am;
182-
} catch (const std::ios_base::failure&) {
183-
}
166+
DeserializeFromFuzzingInput(buffer, am);
184167
#elif BLOCKHEADER_DESERIALIZE
185-
try {
186168
CBlockHeader bh;
187-
ds >> bh;
188-
} catch (const std::ios_base::failure&) {
189-
}
169+
DeserializeFromFuzzingInput(buffer, bh);
190170
#elif BANENTRY_DESERIALIZE
191-
try {
192171
CBanEntry be;
193-
ds >> be;
194-
} catch (const std::ios_base::failure&) {
195-
}
172+
DeserializeFromFuzzingInput(buffer, be);
196173
#elif TXUNDO_DESERIALIZE
197-
try {
198174
CTxUndo tu;
199-
ds >> tu;
200-
} catch (const std::ios_base::failure&) {
201-
}
175+
DeserializeFromFuzzingInput(buffer, tu);
202176
#elif BLOCKUNDO_DESERIALIZE
203-
try {
204177
CBlockUndo bu;
205-
ds >> bu;
206-
} catch (const std::ios_base::failure&) {
207-
}
178+
DeserializeFromFuzzingInput(buffer, bu);
208179
#elif COINS_DESERIALIZE
209-
try {
210180
Coin coin;
211-
ds >> coin;
212-
} catch (const std::ios_base::failure&) {
213-
}
181+
DeserializeFromFuzzingInput(buffer, coin);
214182
#elif NETADDR_DESERIALIZE
215-
try {
216183
CNetAddr na;
217-
ds >> na;
218-
} catch (const std::ios_base::failure&) {
219-
}
184+
DeserializeFromFuzzingInput(buffer, na);
185+
AssertEqualAfterSerializeDeserialize(na);
220186
#elif SERVICE_DESERIALIZE
221-
try {
222187
CService s;
223-
ds >> s;
224-
} catch (const std::ios_base::failure&) {
225-
}
188+
DeserializeFromFuzzingInput(buffer, s);
189+
AssertEqualAfterSerializeDeserialize(s);
226190
#elif MESSAGEHEADER_DESERIALIZE
227-
CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
228-
try {
191+
const CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
229192
CMessageHeader mh(pchMessageStart);
230-
ds >> mh;
193+
DeserializeFromFuzzingInput(buffer, mh);
231194
(void)mh.IsValid(pchMessageStart);
232-
} catch (const std::ios_base::failure&) {
233-
}
234195
#elif ADDRESS_DESERIALIZE
235-
try {
236196
CAddress a;
237-
ds >> a;
238-
} catch (const std::ios_base::failure&) {
239-
}
197+
DeserializeFromFuzzingInput(buffer, a);
240198
#elif INV_DESERIALIZE
241-
try {
242199
CInv i;
243-
ds >> i;
244-
} catch (const std::ios_base::failure&) {
245-
}
200+
DeserializeFromFuzzingInput(buffer, i);
246201
#elif BLOOMFILTER_DESERIALIZE
247-
try {
248202
CBloomFilter bf;
249-
ds >> bf;
250-
} catch (const std::ios_base::failure&) {
251-
}
203+
DeserializeFromFuzzingInput(buffer, bf);
252204
#elif DISKBLOCKINDEX_DESERIALIZE
253-
try {
254205
CDiskBlockIndex dbi;
255-
ds >> dbi;
256-
} catch (const std::ios_base::failure&) {
257-
}
206+
DeserializeFromFuzzingInput(buffer, dbi);
258207
#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);
265211
#elif BLOCKTRANSACTIONS_DESERIALIZE
266-
try {
267212
BlockTransactions bt;
268-
ds >> bt;
269-
} catch (const std::ios_base::failure&) {
270-
}
213+
DeserializeFromFuzzingInput(buffer, bt);
271214
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
272-
try {
273215
BlockTransactionsRequest btr;
274-
ds >> btr;
275-
} catch (const std::ios_base::failure&) {
276-
}
216+
DeserializeFromFuzzingInput(buffer, btr);
277217
#else
278218
#error Need at least one fuzz target to compile
279219
#endif
220+
} catch (const invalid_fuzzing_input_exception&) {
221+
}
280222
}

0 commit comments

Comments
 (0)