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:
    ACK 709afb2a7d 🍲

Tree-SHA512: b8c9c24538ee516607608ac685d2e9b01eca5c15213def3fd096b16516db84bfd45516fbee43e25b28cb3481a5d4ec3f7a34713e2da35b2902081ed42b85224d
This commit is contained in:
MarcoFalke 2019-12-09 15:07:30 -05:00
commit 74c6ad3aab
No known key found for this signature in database
GPG key ID: CE2B75697E69A548

View file

@ -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&) {
}
} }