Merge #17225: tests: Test serialisation as part of deserialisation fuzzing. Test round-trip equality where possible.
709afb2a7d
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: ACK709afb2a7d
🍲 Tree-SHA512: b8c9c24538ee516607608ac685d2e9b01eca5c15213def3fd096b16516db84bfd45516fbee43e25b28cb3481a5d4ec3f7a34713e2da35b2902081ed42b85224d
This commit is contained in:
commit
74c6ad3aab
|
@ -22,6 +22,7 @@
|
||||||
#include <undo.h>
|
#include <undo.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -36,245 +37,186 @@ void initialize()
|
||||||
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
|
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_one_input(const std::vector<uint8_t>& buffer)
|
namespace {
|
||||||
|
|
||||||
|
struct invalid_fuzzing_input_exception : public std::exception {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
CDataStream Serialize(const T& obj)
|
||||||
|
{
|
||||||
|
CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION);
|
||||||
|
ds << obj;
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T Deserialize(CDataStream ds)
|
||||||
|
{
|
||||||
|
T obj;
|
||||||
|
ds >> obj;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj)
|
||||||
{
|
{
|
||||||
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
|
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
|
||||||
try {
|
try {
|
||||||
int nVersion;
|
int version;
|
||||||
ds >> nVersion;
|
ds >> version;
|
||||||
ds.SetVersion(nVersion);
|
ds.SetVersion(version);
|
||||||
} catch (const std::ios_base::failure&) {
|
} catch (const std::ios_base::failure&) {
|
||||||
return;
|
throw invalid_fuzzing_input_exception();
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
ds >> obj;
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
throw invalid_fuzzing_input_exception();
|
||||||
|
}
|
||||||
|
assert(buffer.empty() || !Serialize(obj).empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void AssertEqualAfterSerializeDeserialize(const T& obj)
|
||||||
|
{
|
||||||
|
assert(Deserialize<T>(Serialize(obj)) == obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
try {
|
||||||
#if BLOCK_FILTER_DESERIALIZE
|
#if BLOCK_FILTER_DESERIALIZE
|
||||||
try {
|
|
||||||
BlockFilter block_filter;
|
BlockFilter block_filter;
|
||||||
ds >> block_filter;
|
DeserializeFromFuzzingInput(buffer, block_filter);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif ADDR_INFO_DESERIALIZE
|
#elif ADDR_INFO_DESERIALIZE
|
||||||
try {
|
|
||||||
CAddrInfo addr_info;
|
CAddrInfo addr_info;
|
||||||
ds >> addr_info;
|
DeserializeFromFuzzingInput(buffer, addr_info);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCK_FILE_INFO_DESERIALIZE
|
#elif BLOCK_FILE_INFO_DESERIALIZE
|
||||||
try {
|
|
||||||
CBlockFileInfo block_file_info;
|
CBlockFileInfo block_file_info;
|
||||||
ds >> block_file_info;
|
DeserializeFromFuzzingInput(buffer, block_file_info);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
|
#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
|
||||||
try {
|
|
||||||
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
|
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
|
||||||
ds >> block_header_and_short_txids;
|
DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif FEE_RATE_DESERIALIZE
|
#elif FEE_RATE_DESERIALIZE
|
||||||
try {
|
|
||||||
CFeeRate fee_rate;
|
CFeeRate fee_rate;
|
||||||
ds >> fee_rate;
|
DeserializeFromFuzzingInput(buffer, fee_rate);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(fee_rate);
|
||||||
}
|
|
||||||
#elif MERKLE_BLOCK_DESERIALIZE
|
#elif MERKLE_BLOCK_DESERIALIZE
|
||||||
try {
|
|
||||||
CMerkleBlock merkle_block;
|
CMerkleBlock merkle_block;
|
||||||
ds >> merkle_block;
|
DeserializeFromFuzzingInput(buffer, merkle_block);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif OUT_POINT_DESERIALIZE
|
#elif OUT_POINT_DESERIALIZE
|
||||||
try {
|
|
||||||
COutPoint out_point;
|
COutPoint out_point;
|
||||||
ds >> out_point;
|
DeserializeFromFuzzingInput(buffer, out_point);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(out_point);
|
||||||
}
|
|
||||||
#elif PARTIAL_MERKLE_TREE_DESERIALIZE
|
#elif PARTIAL_MERKLE_TREE_DESERIALIZE
|
||||||
try {
|
|
||||||
CPartialMerkleTree partial_merkle_tree;
|
CPartialMerkleTree partial_merkle_tree;
|
||||||
ds >> partial_merkle_tree;
|
DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif PUB_KEY_DESERIALIZE
|
#elif PUB_KEY_DESERIALIZE
|
||||||
try {
|
|
||||||
CPubKey pub_key;
|
CPubKey pub_key;
|
||||||
ds >> pub_key;
|
DeserializeFromFuzzingInput(buffer, pub_key);
|
||||||
} catch (const std::ios_base::failure&) {
|
// TODO: The following equivalence should hold for CPubKey? Fix.
|
||||||
}
|
// AssertEqualAfterSerializeDeserialize(pub_key);
|
||||||
#elif SCRIPT_DESERIALIZE
|
#elif SCRIPT_DESERIALIZE
|
||||||
try {
|
|
||||||
CScript script;
|
CScript script;
|
||||||
ds >> script;
|
DeserializeFromFuzzingInput(buffer, script);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif SUB_NET_DESERIALIZE
|
#elif SUB_NET_DESERIALIZE
|
||||||
try {
|
|
||||||
CSubNet sub_net;
|
CSubNet sub_net;
|
||||||
ds >> sub_net;
|
DeserializeFromFuzzingInput(buffer, sub_net);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(sub_net);
|
||||||
}
|
|
||||||
#elif TX_IN_DESERIALIZE
|
#elif TX_IN_DESERIALIZE
|
||||||
try {
|
|
||||||
CTxIn tx_in;
|
CTxIn tx_in;
|
||||||
ds >> tx_in;
|
DeserializeFromFuzzingInput(buffer, tx_in);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(tx_in);
|
||||||
}
|
|
||||||
#elif FLAT_FILE_POS_DESERIALIZE
|
#elif FLAT_FILE_POS_DESERIALIZE
|
||||||
try {
|
|
||||||
FlatFilePos flat_file_pos;
|
FlatFilePos flat_file_pos;
|
||||||
ds >> flat_file_pos;
|
DeserializeFromFuzzingInput(buffer, flat_file_pos);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(flat_file_pos);
|
||||||
}
|
|
||||||
#elif KEY_ORIGIN_INFO_DESERIALIZE
|
#elif KEY_ORIGIN_INFO_DESERIALIZE
|
||||||
try {
|
|
||||||
KeyOriginInfo key_origin_info;
|
KeyOriginInfo key_origin_info;
|
||||||
ds >> key_origin_info;
|
DeserializeFromFuzzingInput(buffer, key_origin_info);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(key_origin_info);
|
||||||
}
|
|
||||||
#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
|
#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
|
||||||
try {
|
|
||||||
PartiallySignedTransaction partially_signed_transaction;
|
PartiallySignedTransaction partially_signed_transaction;
|
||||||
ds >> partially_signed_transaction;
|
DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif PREFILLED_TRANSACTION_DESERIALIZE
|
#elif PREFILLED_TRANSACTION_DESERIALIZE
|
||||||
try {
|
|
||||||
PrefilledTransaction prefilled_transaction;
|
PrefilledTransaction prefilled_transaction;
|
||||||
ds >> prefilled_transaction;
|
DeserializeFromFuzzingInput(buffer, prefilled_transaction);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif PSBT_INPUT_DESERIALIZE
|
#elif PSBT_INPUT_DESERIALIZE
|
||||||
try {
|
|
||||||
PSBTInput psbt_input;
|
PSBTInput psbt_input;
|
||||||
ds >> psbt_input;
|
DeserializeFromFuzzingInput(buffer, psbt_input);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif PSBT_OUTPUT_DESERIALIZE
|
#elif PSBT_OUTPUT_DESERIALIZE
|
||||||
try {
|
|
||||||
PSBTOutput psbt_output;
|
PSBTOutput psbt_output;
|
||||||
ds >> psbt_output;
|
DeserializeFromFuzzingInput(buffer, psbt_output);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCK_DESERIALIZE
|
#elif BLOCK_DESERIALIZE
|
||||||
try {
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
ds >> block;
|
DeserializeFromFuzzingInput(buffer, block);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCKLOCATOR_DESERIALIZE
|
#elif BLOCKLOCATOR_DESERIALIZE
|
||||||
try {
|
|
||||||
CBlockLocator bl;
|
CBlockLocator bl;
|
||||||
ds >> bl;
|
DeserializeFromFuzzingInput(buffer, bl);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCKMERKLEROOT
|
#elif BLOCKMERKLEROOT
|
||||||
try {
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
ds >> block;
|
DeserializeFromFuzzingInput(buffer, block);
|
||||||
bool mutated;
|
bool mutated;
|
||||||
BlockMerkleRoot(block, &mutated);
|
BlockMerkleRoot(block, &mutated);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif ADDRMAN_DESERIALIZE
|
#elif ADDRMAN_DESERIALIZE
|
||||||
try {
|
|
||||||
CAddrMan am;
|
CAddrMan am;
|
||||||
ds >> am;
|
DeserializeFromFuzzingInput(buffer, am);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCKHEADER_DESERIALIZE
|
#elif BLOCKHEADER_DESERIALIZE
|
||||||
try {
|
|
||||||
CBlockHeader bh;
|
CBlockHeader bh;
|
||||||
ds >> bh;
|
DeserializeFromFuzzingInput(buffer, bh);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BANENTRY_DESERIALIZE
|
#elif BANENTRY_DESERIALIZE
|
||||||
try {
|
|
||||||
CBanEntry be;
|
CBanEntry be;
|
||||||
ds >> be;
|
DeserializeFromFuzzingInput(buffer, be);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif TXUNDO_DESERIALIZE
|
#elif TXUNDO_DESERIALIZE
|
||||||
try {
|
|
||||||
CTxUndo tu;
|
CTxUndo tu;
|
||||||
ds >> tu;
|
DeserializeFromFuzzingInput(buffer, tu);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCKUNDO_DESERIALIZE
|
#elif BLOCKUNDO_DESERIALIZE
|
||||||
try {
|
|
||||||
CBlockUndo bu;
|
CBlockUndo bu;
|
||||||
ds >> bu;
|
DeserializeFromFuzzingInput(buffer, bu);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif COINS_DESERIALIZE
|
#elif COINS_DESERIALIZE
|
||||||
try {
|
|
||||||
Coin coin;
|
Coin coin;
|
||||||
ds >> coin;
|
DeserializeFromFuzzingInput(buffer, coin);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif NETADDR_DESERIALIZE
|
#elif NETADDR_DESERIALIZE
|
||||||
try {
|
|
||||||
CNetAddr na;
|
CNetAddr na;
|
||||||
ds >> na;
|
DeserializeFromFuzzingInput(buffer, na);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(na);
|
||||||
}
|
|
||||||
#elif SERVICE_DESERIALIZE
|
#elif SERVICE_DESERIALIZE
|
||||||
try {
|
|
||||||
CService s;
|
CService s;
|
||||||
ds >> s;
|
DeserializeFromFuzzingInput(buffer, s);
|
||||||
} catch (const std::ios_base::failure&) {
|
AssertEqualAfterSerializeDeserialize(s);
|
||||||
}
|
|
||||||
#elif MESSAGEHEADER_DESERIALIZE
|
#elif MESSAGEHEADER_DESERIALIZE
|
||||||
CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
|
const CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
|
||||||
try {
|
|
||||||
CMessageHeader mh(pchMessageStart);
|
CMessageHeader mh(pchMessageStart);
|
||||||
ds >> mh;
|
DeserializeFromFuzzingInput(buffer, mh);
|
||||||
(void)mh.IsValid(pchMessageStart);
|
(void)mh.IsValid(pchMessageStart);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif ADDRESS_DESERIALIZE
|
#elif ADDRESS_DESERIALIZE
|
||||||
try {
|
|
||||||
CAddress a;
|
CAddress a;
|
||||||
ds >> a;
|
DeserializeFromFuzzingInput(buffer, a);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif INV_DESERIALIZE
|
#elif INV_DESERIALIZE
|
||||||
try {
|
|
||||||
CInv i;
|
CInv i;
|
||||||
ds >> i;
|
DeserializeFromFuzzingInput(buffer, i);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOOMFILTER_DESERIALIZE
|
#elif BLOOMFILTER_DESERIALIZE
|
||||||
try {
|
|
||||||
CBloomFilter bf;
|
CBloomFilter bf;
|
||||||
ds >> bf;
|
DeserializeFromFuzzingInput(buffer, bf);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif DISKBLOCKINDEX_DESERIALIZE
|
#elif DISKBLOCKINDEX_DESERIALIZE
|
||||||
try {
|
|
||||||
CDiskBlockIndex dbi;
|
CDiskBlockIndex dbi;
|
||||||
ds >> dbi;
|
DeserializeFromFuzzingInput(buffer, dbi);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif TXOUTCOMPRESSOR_DESERIALIZE
|
#elif TXOUTCOMPRESSOR_DESERIALIZE
|
||||||
CTxOut to;
|
CTxOut to;
|
||||||
CTxOutCompressor toc(to);
|
CTxOutCompressor toc(to);
|
||||||
try {
|
DeserializeFromFuzzingInput(buffer, toc);
|
||||||
ds >> toc;
|
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCKTRANSACTIONS_DESERIALIZE
|
#elif BLOCKTRANSACTIONS_DESERIALIZE
|
||||||
try {
|
|
||||||
BlockTransactions bt;
|
BlockTransactions bt;
|
||||||
ds >> bt;
|
DeserializeFromFuzzingInput(buffer, bt);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
|
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
|
||||||
try {
|
|
||||||
BlockTransactionsRequest btr;
|
BlockTransactionsRequest btr;
|
||||||
ds >> btr;
|
DeserializeFromFuzzingInput(buffer, btr);
|
||||||
} catch (const std::ios_base::failure&) {
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
#error Need at least one fuzz target to compile
|
#error Need at least one fuzz target to compile
|
||||||
#endif
|
#endif
|
||||||
|
} catch (const invalid_fuzzing_input_exception&) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue