Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: Add deserialization fuzzing of SnapshotMetadata (utxo_snapshot). Increase fuzzing coverage. #18314

Merged
merged 12 commits into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ FUZZ_TARGETS = \
test/fuzz/script_ops \
test/fuzz/scriptnum_ops \
test/fuzz/service_deserialize \
test/fuzz/snapshotmetadata_deserialize \
test/fuzz/spanparsing \
test/fuzz/strprintf \
test/fuzz/sub_net_deserialize \
Expand All @@ -72,7 +73,9 @@ FUZZ_TARGETS = \
test/fuzz/tx_in_deserialize \
test/fuzz/tx_out \
test/fuzz/txoutcompressor_deserialize \
test/fuzz/txundo_deserialize
test/fuzz/txundo_deserialize \
test/fuzz/uint160_deserialize \
test/fuzz/uint256_deserialize

if ENABLE_FUZZ
noinst_PROGRAMS += $(FUZZ_TARGETS:=)
Expand Down Expand Up @@ -628,6 +631,12 @@ test_fuzz_sub_net_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_sub_net_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_sub_net_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp

test_fuzz_snapshotmetadata_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSNAPSHOTMETADATA_DESERIALIZE=1
test_fuzz_snapshotmetadata_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_snapshotmetadata_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_snapshotmetadata_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_snapshotmetadata_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp

test_fuzz_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
Expand Down Expand Up @@ -664,6 +673,18 @@ test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_txundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_txundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp

test_fuzz_uint160_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT160_DESERIALIZE=1
test_fuzz_uint160_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_uint160_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_uint160_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_uint160_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp

test_fuzz_uint256_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT256_DESERIALIZE=1
test_fuzz_uint256_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_uint256_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_uint256_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_uint256_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp

endif # ENABLE_FUZZ

nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
Expand Down
5 changes: 5 additions & 0 deletions src/test/fuzz/base_encode_decode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <test/fuzz/fuzz.h>

#include <base58.h>
#include <psbt.h>
#include <util/string.h>
#include <util/strencodings.h>

Expand Down Expand Up @@ -44,4 +45,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
assert(encoded_string == TrimString(encoded_string));
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
}

PartiallySignedTransaction psbt;
std::string error;
(void)DecodeBase64PSBT(psbt, random_encoded_string, error);
}
6 changes: 4 additions & 2 deletions src/test/fuzz/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

void initialize()
{
const static auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}

Expand Down Expand Up @@ -59,5 +59,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
(void)GetBlockWeight(block);
(void)GetWitnessCommitmentIndex(block);
(void)RecursiveDynamicUsage(block);
const size_t raw_memory_size = RecursiveDynamicUsage(block);
const size_t raw_memory_size_as_shared_ptr = RecursiveDynamicUsage(std::make_shared<CBlock>(block));
assert(raw_memory_size_as_shared_ptr > raw_memory_size);
}
2 changes: 1 addition & 1 deletion src/test/fuzz/descriptor_parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

void initialize()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}

Expand Down
18 changes: 17 additions & 1 deletion src/test/fuzz/deserialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <key.h>
#include <merkleblock.h>
#include <net.h>
#include <node/utxo_snapshot.h>
#include <primitives/block.h>
#include <protocol.h>
#include <psbt.h>
Expand All @@ -34,7 +35,7 @@
void initialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
}

namespace {
Expand Down Expand Up @@ -214,9 +215,24 @@ void test_one_input(const std::vector<uint8_t>& buffer)
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
BlockTransactionsRequest btr;
DeserializeFromFuzzingInput(buffer, btr);
#elif SNAPSHOTMETADATA_DESERIALIZE
SnapshotMetadata snapshot_metadata;
DeserializeFromFuzzingInput(buffer, snapshot_metadata);
#elif UINT160_DESERIALIZE
uint160 u160;
DeserializeFromFuzzingInput(buffer, u160);
AssertEqualAfterSerializeDeserialize(u160);
#elif UINT256_DESERIALIZE
uint256 u256;
DeserializeFromFuzzingInput(buffer, u256);
AssertEqualAfterSerializeDeserialize(u256);
#else
#error Need at least one fuzz target to compile
#endif
// 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
} catch (const invalid_fuzzing_input_exception&) {
}
}
2 changes: 1 addition & 1 deletion src/test/fuzz/eval_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

void initialize()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
}

void test_one_input(const std::vector<uint8_t>& buffer)
Expand Down
7 changes: 7 additions & 0 deletions src/test/fuzz/hex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <core_io.h>
#include <pubkey.h>
#include <primitives/block.h>
#include <rpc/util.h>
#include <test/fuzz/fuzz.h>
Expand All @@ -15,6 +16,10 @@
#include <string>
#include <vector>

void initialize() {
static const ECCVerifyHandle verify_handle;
}

void test_one_input(const std::vector<uint8_t>& buffer)
{
const std::string random_hex_string(buffer.begin(), buffer.end());
Expand All @@ -33,4 +38,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
CBlockHeader block_header;
(void)DecodeHexBlockHeader(block_header, random_hex_string);
CBlock block;
(void)DecodeHexBlk(block, random_hex_string);
}
7 changes: 7 additions & 0 deletions src/test/fuzz/integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <netbase.h>
#include <policy/settings.h>
#include <pow.h>
#include <protocol.h>
#include <pubkey.h>
#include <rpc/util.h>
#include <script/signingprovider.h>
Expand Down Expand Up @@ -216,4 +217,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
stream >> deserialized_b;
assert(b == deserialized_b && stream.empty());
}

{
const ServiceFlags service_flags = (ServiceFlags)u64;
(void)HasAllDesirableServiceFlags(service_flags);
(void)MayHaveUsefulAddressDB(service_flags);
}
}
11 changes: 11 additions & 0 deletions src/test/fuzz/netaddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,15 @@ void test_one_input(const std::vector<uint8_t>& buffer)
const CNetAddr other_net_addr = ConsumeNetAddr(fuzzed_data_provider);
(void)net_addr.GetReachabilityFrom(&other_net_addr);
(void)sub_net.Match(other_net_addr);

const CService other_service{net_addr, fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
assert((service == other_service) != (service != other_service));
(void)(service < other_service);

const CSubNet sub_net_copy_1{net_addr, other_net_addr};
const CSubNet sub_net_copy_2{net_addr};

CNetAddr mutable_net_addr;
mutable_net_addr.SetIP(net_addr);
assert(net_addr == mutable_net_addr);
}
18 changes: 16 additions & 2 deletions src/test/fuzz/parse_univalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

void initialize()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}

Expand All @@ -35,21 +35,31 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
try {
(void)ParseHashO(univalue, "A");
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHashO(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHashV(univalue, "A");
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHashV(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHexO(univalue, "A");
} catch (const UniValue&) {
}
try {
(void)ParseHexO(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHexUV(univalue, "A");
Expand All @@ -59,6 +69,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
try {
(void)ParseHexV(univalue, "A");
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
}
try {
(void)ParseHexV(univalue, random_string);
} catch (const UniValue&) {
} catch (const std::runtime_error&) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/psbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

void initialize()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
}

void test_one_input(const std::vector<uint8_t>& buffer)
Expand Down
21 changes: 13 additions & 8 deletions src/test/fuzz/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
#include <script/signingprovider.h>
#include <script/standard.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <univalue.h>
#include <util/memory.h>

void initialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;

SelectParams(CBaseChainParams::REGTEST);
}
Expand All @@ -41,13 +43,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
assert(script == decompressed_script);
}

for (unsigned int size = 0; size < 6; ++size) {
std::vector<unsigned char> vch(GetSpecialScriptSize(size), 0x00);
vch.insert(vch.end(), buffer.begin(), buffer.end());
CScript decompressed_script;
(void)DecompressScript(decompressed_script, size, vch);
}

CTxDestination address;
(void)ExtractDestination(script, address);

Expand Down Expand Up @@ -92,4 +87,14 @@ void test_one_input(const std::vector<uint8_t>& buffer)
ScriptToUniv(script, o3, true);
UniValue o4(UniValue::VOBJ);
ScriptToUniv(script, o4, false);

{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
// DecompressScript(..., ..., bytes) is not guaranteed to be defined if bytes.size() <= 23.
if (bytes.size() >= 24) {
CScript decompressed_script;
DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), bytes);
}
}
}
2 changes: 1 addition & 1 deletion src/test/fuzz/script_flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ static bool IsValidFlagCombination(unsigned flags);

void initialize()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
static const ECCVerifyHandle verify_handle;
}

void test_one_input(const std::vector<uint8_t>& buffer)
Expand Down
2 changes: 2 additions & 0 deletions src/test/fuzz/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
if (!skip_tx_to_univ) {
TxToUniv(tx, /* hashBlock */ {}, u);
static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
TxToUniv(tx, u256_max, u);
}
}