Bitcoin Core  22.99.0
P2P Digital Currency
deserialize.cpp
Go to the documentation of this file.
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 <compressor.h>
13 #include <consensus/merkle.h>
14 #include <key.h>
15 #include <merkleblock.h>
16 #include <net.h>
17 #include <netbase.h>
18 #include <node/utxo_snapshot.h>
19 #include <primitives/block.h>
20 #include <protocol.h>
21 #include <psbt.h>
22 #include <pubkey.h>
23 #include <script/keyorigin.h>
24 #include <streams.h>
25 #include <test/util/setup_common.h>
26 #include <undo.h>
27 #include <util/system.h>
28 #include <version.h>
29 
30 #include <exception>
31 #include <optional>
32 #include <stdexcept>
33 #include <stdint.h>
34 #include <unistd.h>
35 
36 #include <test/fuzz/fuzz.h>
37 
39 
40 namespace {
41 const BasicTestingSetup* g_setup;
42 } // namespace
43 
45 {
46  static const auto testing_setup = MakeNoLogFileContext<>();
47  g_setup = testing_setup.get();
48 
49  // Fuzzers using pubkey must hold an ECCVerifyHandle.
50  static const ECCVerifyHandle verify_handle;
51 }
52 
53 #define FUZZ_TARGET_DESERIALIZE(name, code) \
54  FUZZ_TARGET_INIT(name, initialize_deserialize) \
55  { \
56  try { \
57  code \
58  } catch (const invalid_fuzzing_input_exception&) { \
59  } \
60  }
61 
62 namespace {
63 
64 struct invalid_fuzzing_input_exception : public std::exception {
65 };
66 
67 template <typename T>
68 CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION, const int ser_type = SER_NETWORK)
69 {
70  CDataStream ds(ser_type, version);
71  ds << obj;
72  return ds;
73 }
74 
75 template <typename T>
76 T Deserialize(CDataStream ds)
77 {
78  T obj;
79  ds >> obj;
80  return obj;
81 }
82 
83 template <typename T>
84 void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optional<int> protocol_version = std::nullopt, const int ser_type = SER_NETWORK)
85 {
86  CDataStream ds(buffer, ser_type, INIT_PROTO_VERSION);
87  if (protocol_version) {
88  ds.SetVersion(*protocol_version);
89  } else {
90  try {
91  int version;
92  ds >> version;
93  ds.SetVersion(version);
94  } catch (const std::ios_base::failure&) {
95  throw invalid_fuzzing_input_exception();
96  }
97  }
98  try {
99  ds >> obj;
100  } catch (const std::ios_base::failure&) {
101  throw invalid_fuzzing_input_exception();
102  }
103  assert(buffer.empty() || !Serialize(obj).empty());
104 }
105 
106 template <typename T>
107 void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION, const int ser_type = SER_NETWORK)
108 {
109  assert(Deserialize<T>(Serialize(obj, version, ser_type)) == obj);
110 }
111 
112 } // namespace
113 
114 FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
115  BlockFilter block_filter;
116  DeserializeFromFuzzingInput(buffer, block_filter);
117 })
118 FUZZ_TARGET_DESERIALIZE(addr_info_deserialize, {
119  AddrInfo addr_info;
120  DeserializeFromFuzzingInput(buffer, addr_info);
121 })
122 FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
123  CBlockFileInfo block_file_info;
124  DeserializeFromFuzzingInput(buffer, block_file_info);
125 })
126 FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
127  CBlockHeaderAndShortTxIDs block_header_and_short_txids;
128  DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
129 })
130 FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
131  CFeeRate fee_rate;
132  DeserializeFromFuzzingInput(buffer, fee_rate);
134 })
135 FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
136  CMerkleBlock merkle_block;
137  DeserializeFromFuzzingInput(buffer, merkle_block);
138 })
139 FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
140  COutPoint out_point;
141  DeserializeFromFuzzingInput(buffer, out_point);
143 })
144 FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
145  CPartialMerkleTree partial_merkle_tree;
146  DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
147 })
148 FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
149  CPubKey pub_key;
150  DeserializeFromFuzzingInput(buffer, pub_key);
152 })
153 FUZZ_TARGET_DESERIALIZE(script_deserialize, {
154  CScript script;
155  DeserializeFromFuzzingInput(buffer, script);
156 })
157 FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
158  CTxIn tx_in;
159  DeserializeFromFuzzingInput(buffer, tx_in);
161 })
162 FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
163  FlatFilePos flat_file_pos;
164  DeserializeFromFuzzingInput(buffer, flat_file_pos);
166 })
167 FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
168  KeyOriginInfo key_origin_info;
169  DeserializeFromFuzzingInput(buffer, key_origin_info);
170  AssertEqualAfterSerializeDeserialize(key_origin_info);
171 })
172 FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
173  PartiallySignedTransaction partially_signed_transaction;
174  DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
175 })
176 FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
177  PrefilledTransaction prefilled_transaction;
178  DeserializeFromFuzzingInput(buffer, prefilled_transaction);
179 })
180 FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
181  PSBTInput psbt_input;
182  DeserializeFromFuzzingInput(buffer, psbt_input);
183 })
184 FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
185  PSBTOutput psbt_output;
186  DeserializeFromFuzzingInput(buffer, psbt_output);
187 })
188 FUZZ_TARGET_DESERIALIZE(block_deserialize, {
189  CBlock block;
190  DeserializeFromFuzzingInput(buffer, block);
191 })
192 FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
193  CBlockLocator bl;
194  DeserializeFromFuzzingInput(buffer, bl);
195 })
196 FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
197  CBlock block;
198  DeserializeFromFuzzingInput(buffer, block);
199  bool mutated;
200  BlockMerkleRoot(block, &mutated);
201 })
202 FUZZ_TARGET_DESERIALIZE(addrman_deserialize, {
203  AddrMan am(/*asmap=*/std::vector<bool>(),
204  /*deterministic=*/false,
205  g_setup->m_node.args->GetIntArg("-checkaddrman", 0));
206  DeserializeFromFuzzingInput(buffer, am);
207 })
208 FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
209  CBlockHeader bh;
210  DeserializeFromFuzzingInput(buffer, bh);
211 })
212 FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
213  CTxUndo tu;
214  DeserializeFromFuzzingInput(buffer, tu);
215 })
216 FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
217  CBlockUndo bu;
218  DeserializeFromFuzzingInput(buffer, bu);
219 })
220 FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
221  Coin coin;
222  DeserializeFromFuzzingInput(buffer, coin);
223 })
224 FUZZ_TARGET_DESERIALIZE(netaddr_deserialize, {
225  CNetAddr na;
226  DeserializeFromFuzzingInput(buffer, na);
227  if (na.IsAddrV1Compatible()) {
229  }
231 })
232 FUZZ_TARGET_DESERIALIZE(service_deserialize, {
233  CService s;
234  DeserializeFromFuzzingInput(buffer, s);
235  if (s.IsAddrV1Compatible()) {
237  }
239  CService s1;
243  CService s2;
246 })
247 FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
248  CMessageHeader mh;
249  DeserializeFromFuzzingInput(buffer, mh);
250  (void)mh.IsCommandValid();
251 })
252 FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_notime, {
253  CAddress a;
255  // A CAddress without nTime (as is expected under INIT_PROTO_VERSION) will roundtrip
256  // in all 5 formats (with/without nTime, v1/v2, network/disk)
262 })
263 FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_withtime, {
264  CAddress a;
266  // A CAddress in V1 mode will roundtrip in all 4 formats that have nTime.
271 })
272 FUZZ_TARGET_DESERIALIZE(address_deserialize_v2, {
273  CAddress a;
275  // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
276  // with time if it's V1 compatible.
277  if (a.IsAddrV1Compatible()) {
280  }
283 })
284 FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
285  CInv i;
286  DeserializeFromFuzzingInput(buffer, i);
287 })
288 FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
289  CBloomFilter bf;
290  DeserializeFromFuzzingInput(buffer, bf);
291 })
292 FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
293  CDiskBlockIndex dbi;
294  DeserializeFromFuzzingInput(buffer, dbi);
295 })
296 FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
297  CTxOut to;
298  auto toc = Using<TxOutCompression>(to);
299  DeserializeFromFuzzingInput(buffer, toc);
300 })
301 FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
303  DeserializeFromFuzzingInput(buffer, bt);
304 })
305 FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
307  DeserializeFromFuzzingInput(buffer, btr);
308 })
309 FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
310  SnapshotMetadata snapshot_metadata;
311  DeserializeFromFuzzingInput(buffer, snapshot_metadata);
312 })
313 FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
314  uint160 u160;
315  DeserializeFromFuzzingInput(buffer, u160);
317 })
318 FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
319  uint256 u256;
320  DeserializeFromFuzzingInput(buffer, u256);
322 })
323 // Classes intentionally not covered in this file since their deserialization code is
324 // fuzzed elsewhere:
325 // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
326 // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
ADDRV2_FORMAT
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
Definition: netaddress.h:34
CTxIn
An input of a transaction.
Definition: transaction.h:65
block.h
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:528
merkleblock.h
assert
assert(!tx.IsCoinBase())
SER_DISK
@ SER_DISK
Definition: serialize.h:132
CPartialMerkleTree
Data structure that represents a partial merkle tree.
Definition: merkleblock.h:54
node::SnapshotMetadata
Metadata describing a serialized version of a UTXO set from which an assumeutxo CChainState can be co...
Definition: utxo_snapshot.h:15
CBlockHeader
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:20
CTxUndo
Undo information for a CTransaction.
Definition: undo.h:53
addrman_impl.h
streams.h
CBloomFilter
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
Definition: bloom.h:44
setup_common.h
BlockTransactions
Definition: blockencodings.h:51
CNetAddr
Network address.
Definition: netaddress.h:118
CMerkleBlock
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
Definition: merkleblock.h:124
AddrMan
Stochastic address manager.
Definition: addrman.h:79
PrefilledTransaction
Definition: blockencodings.h:68
AddrInfo
Extended statistics about a CAddress.
Definition: addrman_impl.h:37
CDiskBlockIndex
Used to marshal pointers into hashes for db storage.
Definition: chain.h:368
pubkey.h
CInv
inv message data
Definition: protocol.h:476
version.h
Serialize
void Serialize(Stream &, char)=delete
CFeeRate
Fee rate in satoshis per kilobyte: CAmount / kB.
Definition: feerate.h:29
mutated
bool mutated
Definition: deserialize.cpp:199
compressor.h
Span
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:96
addrdb.h
BlockTransactionsRequest
Definition: blockencodings.h:39
CTxOut
An output of a transaction.
Definition: transaction.h:148
Coin
A UTXO entry.
Definition: coins.h:30
FlatFilePos
Definition: flatfile.h:14
undo.h
blockencodings.h
CMessageHeader::IsCommandValid
bool IsCommandValid() const
Definition: protocol.cpp:107
BasicTestingSetup
Basic testing setup.
Definition: setup_common.h:83
PSBTOutput
A structure for PSBTs which contains per output information.
Definition: psbt.h:531
utxo_snapshot.h
uint256
256-bit opaque blob.
Definition: uint256.h:126
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:405
coins.h
merkle.h
CDataStream::SetVersion
void SetVersion(int n)
Definition: streams.h:276
Span::empty
constexpr bool empty() const noexcept
Definition: span.h:188
system.h
CBlock
Definition: block.h:62
DeserializeFromFuzzingInput
DeserializeFromFuzzingInput(buffer, addr_info)
CBlockHeaderAndShortTxIDs
Definition: blockencodings.h:86
key.h
uint160
160-bit opaque blob.
Definition: uint256.h:115
CPubKey
An encapsulated public key.
Definition: pubkey.h:33
CAddress
A CService with information about it as peer.
Definition: protocol.h:358
CMessageHeader
Message header.
Definition: protocol.h:30
PSBTInput
A structure for PSBTs which contain per-input information.
Definition: psbt.h:168
ECCVerifyHandle
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:332
BlockMerkleRoot
BlockMerkleRoot(block, &mutated)
fuzz.h
PartiallySignedTransaction
A version of CTransaction with the PSBT format.
Definition: psbt.h:668
CBlockFileInfo
Definition: chain.h:43
AssertEqualAfterSerializeDeserialize
AssertEqualAfterSerializeDeserialize(flat_file_pos)
initialize_deserialize
void initialize_deserialize()
Definition: deserialize.cpp:44
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:184
addrman.h
SER_NETWORK
@ SER_NETWORK
Definition: serialize.h:131
netbase.h
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:26
CNetAddr::IsAddrV1Compatible
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Definition: netaddress.cpp:505
keyorigin.h
CBlockLocator
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:114
T
#define T(expected, seed, data)
FUZZ_TARGET_DESERIALIZE
#define FUZZ_TARGET_DESERIALIZE(name, code)
Definition: deserialize.cpp:53
KeyOriginInfo
Definition: keyorigin.h:11
CBlockUndo
Undo information for a CBlock.
Definition: undo.h:63
INIT_PROTO_VERSION
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
Definition: version.h:15
PROTOCOL_VERSION
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12
BlockFilter
Complete block filter struct as defined in BIP 157.
Definition: blockfilter.h:110