0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-23 12:33:26 -05:00
bitcoin-bitcoin-core/src/test/fuzz/deserialize.cpp

337 lines
11 KiB
C++
Raw Normal View History

// Copyright (c) 2009-2021 The Bitcoin Core developers
2016-04-22 15:19:33 -07:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrdb.h>
#include <addrman.h>
#include <addrman_impl.h>
#include <blockencodings.h>
#include <blockfilter.h>
#include <chain.h>
#include <coins.h>
#include <common/args.h>
#include <compressor.h>
#include <consensus/merkle.h>
#include <key.h>
#include <merkleblock.h>
#include <net.h>
#include <netbase.h>
2021-08-31 18:40:18 +01:00
#include <netgroup.h>
#include <node/utxo_snapshot.h>
#include <primitives/block.h>
#include <protocol.h>
#include <psbt.h>
#include <pubkey.h>
#include <script/keyorigin.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <undo.h>
2016-04-22 15:19:33 -07:00
#include <exception>
#include <optional>
#include <stdexcept>
2016-04-22 15:19:33 -07:00
#include <stdint.h>
#include <unistd.h>
using node::SnapshotMetadata;
namespace {
const BasicTestingSetup* g_setup;
} // namespace
2020-12-03 16:42:49 +01:00
void initialize_deserialize()
{
static const auto testing_setup = MakeNoLogFileContext<>();
g_setup = testing_setup.get();
}
2020-12-03 16:42:49 +01:00
#define FUZZ_TARGET_DESERIALIZE(name, code) \
FUZZ_TARGET(name, .init = initialize_deserialize) \
2020-12-03 16:42:49 +01:00
{ \
try { \
code \
} catch (const invalid_fuzzing_input_exception&) { \
} \
}
namespace {
struct invalid_fuzzing_input_exception : public std::exception {
};
template <typename T, typename P>
DataStream Serialize(const T& obj, const P& params)
{
DataStream ds{};
ds << params(obj);
return ds;
}
template <typename T, typename P>
T Deserialize(DataStream&& ds, const P& params)
{
T obj;
ds >> params(obj);
return obj;
}
template <typename T, typename P>
void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj, const P& params)
{
DataStream ds{buffer};
try {
ds >> params(obj);
} catch (const std::ios_base::failure&) {
throw invalid_fuzzing_input_exception();
}
assert(buffer.empty() || !Serialize(obj, params).empty());
}
template <typename T>
DataStream Serialize(const T& obj)
{
DataStream ds{};
ds << obj;
return ds;
}
template <typename T>
T Deserialize(DataStream ds)
{
T obj;
ds >> obj;
return obj;
}
template <typename T>
void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj)
{
DataStream ds{buffer};
try {
ds >> obj;
} catch (const std::ios_base::failure&) {
throw invalid_fuzzing_input_exception();
}
assert(buffer.empty() || !Serialize(obj).empty());
}
template <typename T, typename P>
void AssertEqualAfterSerializeDeserialize(const T& obj, const P& params)
{
assert(Deserialize<T>(Serialize(obj, params), params) == obj);
}
template <typename T>
void AssertEqualAfterSerializeDeserialize(const T& obj)
{
assert(Deserialize<T>(Serialize(obj)) == obj);
}
} // namespace
2020-12-03 16:42:49 +01:00
FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
BlockFilter block_filter;
DeserializeFromFuzzingInput(buffer, block_filter);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET(addr_info_deserialize, .init = initialize_deserialize)
{
FuzzedDataProvider fdp{buffer.data(), buffer.size()};
(void)ConsumeDeserializable<AddrInfo>(fdp, ConsumeDeserializationParams<CAddress::SerParams>(fdp));
}
2020-12-03 16:42:49 +01:00
FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
CBlockFileInfo block_file_info;
DeserializeFromFuzzingInput(buffer, block_file_info);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
CFeeRate fee_rate;
DeserializeFromFuzzingInput(buffer, fee_rate);
AssertEqualAfterSerializeDeserialize(fee_rate);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
CMerkleBlock merkle_block;
DeserializeFromFuzzingInput(buffer, merkle_block);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
COutPoint out_point;
DeserializeFromFuzzingInput(buffer, out_point);
AssertEqualAfterSerializeDeserialize(out_point);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
CPartialMerkleTree partial_merkle_tree;
DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
CPubKey pub_key;
DeserializeFromFuzzingInput(buffer, pub_key);
AssertEqualAfterSerializeDeserialize(pub_key);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(script_deserialize, {
CScript script;
DeserializeFromFuzzingInput(buffer, script);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
CTxIn tx_in;
DeserializeFromFuzzingInput(buffer, tx_in);
AssertEqualAfterSerializeDeserialize(tx_in);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
FlatFilePos flat_file_pos;
DeserializeFromFuzzingInput(buffer, flat_file_pos);
AssertEqualAfterSerializeDeserialize(flat_file_pos);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
KeyOriginInfo key_origin_info;
DeserializeFromFuzzingInput(buffer, key_origin_info);
AssertEqualAfterSerializeDeserialize(key_origin_info);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
PartiallySignedTransaction partially_signed_transaction;
DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
PrefilledTransaction prefilled_transaction;
DeserializeFromFuzzingInput(buffer, prefilled_transaction);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
PSBTInput psbt_input;
DeserializeFromFuzzingInput(buffer, psbt_input);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
PSBTOutput psbt_output;
DeserializeFromFuzzingInput(buffer, psbt_output);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(block_deserialize, {
CBlock block;
DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
CBlockLocator bl;
DeserializeFromFuzzingInput(buffer, bl);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
CBlock block;
DeserializeFromFuzzingInput(buffer, TX_WITH_WITNESS(block));
bool mutated;
BlockMerkleRoot(block, &mutated);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
CBlockHeader bh;
DeserializeFromFuzzingInput(buffer, bh);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
CTxUndo tu;
DeserializeFromFuzzingInput(buffer, tu);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
CBlockUndo bu;
DeserializeFromFuzzingInput(buffer, bu);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
Coin coin;
DeserializeFromFuzzingInput(buffer, coin);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET(netaddr_deserialize, .init = initialize_deserialize)
{
FuzzedDataProvider fdp{buffer.data(), buffer.size()};
const auto maybe_na{ConsumeDeserializable<CNetAddr>(fdp, ConsumeDeserializationParams<CNetAddr::SerParams>(fdp))};
if (!maybe_na) return;
const CNetAddr& na{*maybe_na};
if (na.IsAddrV1Compatible()) {
AssertEqualAfterSerializeDeserialize(na, CNetAddr::V1);
}
AssertEqualAfterSerializeDeserialize(na, CNetAddr::V2);
}
FUZZ_TARGET(service_deserialize, .init = initialize_deserialize)
{
FuzzedDataProvider fdp{buffer.data(), buffer.size()};
const auto ser_params{ConsumeDeserializationParams<CNetAddr::SerParams>(fdp)};
const auto maybe_s{ConsumeDeserializable<CService>(fdp, ser_params)};
if (!maybe_s) return;
const CService& s{*maybe_s};
if (s.IsAddrV1Compatible()) {
AssertEqualAfterSerializeDeserialize(s, CNetAddr::V1);
}
AssertEqualAfterSerializeDeserialize(s, CNetAddr::V2);
if (ser_params.enc == CNetAddr::Encoding::V1) {
assert(s.IsAddrV1Compatible());
}
}
2020-12-03 16:42:49 +01:00
FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
CMessageHeader mh;
DeserializeFromFuzzingInput(buffer, mh);
(void)mh.IsCommandValid();
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET(address_deserialize, .init = initialize_deserialize)
{
FuzzedDataProvider fdp{buffer.data(), buffer.size()};
const auto ser_enc{ConsumeDeserializationParams<CAddress::SerParams>(fdp)};
const auto maybe_a{ConsumeDeserializable<CAddress>(fdp, ser_enc)};
if (!maybe_a) return;
const CAddress& a{*maybe_a};
// A CAddress in V1 mode will roundtrip
// in all 4 formats (v1/v2, network/disk)
if (ser_enc.enc == CNetAddr::Encoding::V1) {
AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
} else {
// A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
// if it's V1 compatible.
if (a.IsAddrV1Compatible()) {
AssertEqualAfterSerializeDeserialize(a, CAddress::V1_DISK);
AssertEqualAfterSerializeDeserialize(a, CAddress::V1_NETWORK);
}
AssertEqualAfterSerializeDeserialize(a, CAddress::V2_NETWORK);
AssertEqualAfterSerializeDeserialize(a, CAddress::V2_DISK);
}
}
2020-12-03 16:42:49 +01:00
FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
CInv i;
DeserializeFromFuzzingInput(buffer, i);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
CBloomFilter bf;
DeserializeFromFuzzingInput(buffer, bf);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
CDiskBlockIndex dbi;
DeserializeFromFuzzingInput(buffer, dbi);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
CTxOut to;
auto toc = Using<TxOutCompression>(to);
DeserializeFromFuzzingInput(buffer, toc);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
BlockTransactions bt;
DeserializeFromFuzzingInput(buffer, bt);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
BlockTransactionsRequest btr;
DeserializeFromFuzzingInput(buffer, btr);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
SnapshotMetadata snapshot_metadata;
DeserializeFromFuzzingInput(buffer, snapshot_metadata);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
uint160 u160;
DeserializeFromFuzzingInput(buffer, u160);
AssertEqualAfterSerializeDeserialize(u160);
2020-12-03 16:42:49 +01:00
})
FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
uint256 u256;
DeserializeFromFuzzingInput(buffer, u256);
AssertEqualAfterSerializeDeserialize(u256);
})
// Classes intentionally not covered in this file since their deserialization code is
// fuzzed elsewhere:
// * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
// * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp