Skip to content

Commit

Permalink
partial bitcoin#18314: Add deserialization fuzzing of SnapshotMetadat…
Browse files Browse the repository at this point in the history
…a (utxo_snapshot). Increase fuzzing coverage
  • Loading branch information
kwvg committed Jul 6, 2022
1 parent 0c0947e commit 75fa4ba
Show file tree
Hide file tree
Showing 13 changed files with 95 additions and 17 deletions.
16 changes: 15 additions & 1 deletion src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,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 @@ -827,6 +829,18 @@ test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_txundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(LDFLAGS_WRAP_EXCEPTIONS)
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) $(LDFLAGS_WRAP_EXCEPTIONS)
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) $(LDFLAGS_WRAP_EXCEPTIONS)
test_fuzz_uint256_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
endif # ENABLE_FUZZ

nodist_test_test_dash_SOURCES = $(GENERATED_TEST_FILES)
Expand Down
6 changes: 6 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,8 @@
#include <test/fuzz/fuzz.h>

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

Expand Down Expand Up @@ -44,4 +46,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 @@ -52,5 +52,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)block.GetHash();
(void)block.ToString();
(void)BlockMerkleRoot(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 @@ -12,7 +12,7 @@

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

Expand Down
14 changes: 13 additions & 1 deletion src/test/fuzz/deserialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,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 @@ -220,9 +220,21 @@ void test_one_input(const std::vector<uint8_t>& buffer)
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
BlockTransactionsRequest btr;
DeserializeFromFuzzingInput(buffer, btr);
#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);
}
5 changes: 5 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/sign.h>
Expand Down Expand Up @@ -220,6 +221,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
assert(b == deserialized_b && stream.empty());
}

const ServiceFlags service_flags = (ServiceFlags)u64;
(void)HasAllDesirableServiceFlags(service_flags);
(void)MayHaveUsefulAddressDB(service_flags);

{
CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);

Expand Down
11 changes: 11 additions & 0 deletions src/test/fuzz/netaddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,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 @@ -16,7 +16,7 @@

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

Expand All @@ -37,21 +37,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 @@ -61,6 +71,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
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/sign.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 @@ -39,13 +41,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
assert(ok);
}

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 @@ -84,4 +79,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 @@ -100,5 +100,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);
}
}

0 comments on commit 75fa4ba

Please sign in to comment.