Merge #19143: tests: Add fuzzing harnesses for CAutoFile, CBufferedFile, LoadExternalBlockFile and other FILE* consumers
ad6c34881d
tests: Add fuzzing harness for CBlockPolicyEstimator::{Read,Write} (policy/fees.h) (practicalswift)614e0807a8
tests: Add fuzzing harness for CBufferedFile::{SetPos,GetPos,GetType,GetVersion} (stream.h) (practicalswift)7bcc71e5f8
tests: Add fuzzing harness for LoadExternalBlockFile(...) (validation.h) (practicalswift)9823376030
tests: Add fuzzing harness for CBufferedFile (streams.h) (practicalswift)f3aa659be6
tests: Add fuzzing harness for CAutoFile (streams.h) (practicalswift)e507c0799d
tests: Add serialization/deserialization fuzzing helpers WriteToStream(…)/ReadFromStream(…) (practicalswift)e48094a506
tests: Add FuzzedAutoFileProvider which provides a CAutoFile interface to FuzzedDataProvider (practicalswift)9dbcd6854c
tests: Add FuzzedFileProvider which provides a FILE* interface to FuzzedDataProvider using fopencookie (practicalswift) Pull request description: Add fuzzing harnesses for `CAutoFile`, `CBufferedFile`, `LoadExternalBlockFile` and other `FILE*` consumers: * Add `FuzzedFileProvider` which provides a `FILE*` interface to `FuzzedDataProvider` using `fopencookie` * Add `FuzzedAutoFileProvider` which provides a `CAutoFile` interface to `FuzzedDataProvider` * Add serialization/deserialization fuzzing helpers `WriteToStream(…)`/`ReadFromStream(…)` * Add fuzzing harness for `CAutoFile` (`streams.h`) * Add fuzzing harness for `CBufferedFile` (`streams.h`) * Add fuzzing harness for `LoadExternalBlockFile(...)` (`validation.h`) * Add fuzzing harness for `CBlockPolicyEstimator::Read` and `CBlockPolicyEstimator::Write` (`policy/fees.h`) See [`doc/fuzzing.md`](https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md) for information on how to fuzz Bitcoin Core. Don't forget to contribute any coverage increasing inputs you find to the [Bitcoin Core fuzzing corpus repo](https://github.com/bitcoin-core/qa-assets). Happy fuzzing :) ACKs for top commit: Crypt-iQ: Tested ACKad6c348
Tree-SHA512: a38e142608218496796a527d7e59b74e30279a2815450408b7c27a76ed600cebc6b88491e831665a0639671e2d212453fcdca558500bbadbeb32b267751f8f72
This commit is contained in:
commit
090d877160
7 changed files with 454 additions and 0 deletions
|
@ -10,6 +10,7 @@ FUZZ_TARGETS = \
|
||||||
test/fuzz/addrman_deserialize \
|
test/fuzz/addrman_deserialize \
|
||||||
test/fuzz/asmap \
|
test/fuzz/asmap \
|
||||||
test/fuzz/asmap_direct \
|
test/fuzz/asmap_direct \
|
||||||
|
test/fuzz/autofile \
|
||||||
test/fuzz/banentry_deserialize \
|
test/fuzz/banentry_deserialize \
|
||||||
test/fuzz/banman \
|
test/fuzz/banman \
|
||||||
test/fuzz/base_encode_decode \
|
test/fuzz/base_encode_decode \
|
||||||
|
@ -29,6 +30,7 @@ FUZZ_TARGETS = \
|
||||||
test/fuzz/blockundo_deserialize \
|
test/fuzz/blockundo_deserialize \
|
||||||
test/fuzz/bloom_filter \
|
test/fuzz/bloom_filter \
|
||||||
test/fuzz/bloomfilter_deserialize \
|
test/fuzz/bloomfilter_deserialize \
|
||||||
|
test/fuzz/buffered_file \
|
||||||
test/fuzz/chain \
|
test/fuzz/chain \
|
||||||
test/fuzz/checkqueue \
|
test/fuzz/checkqueue \
|
||||||
test/fuzz/coins_deserialize \
|
test/fuzz/coins_deserialize \
|
||||||
|
@ -61,6 +63,7 @@ FUZZ_TARGETS = \
|
||||||
test/fuzz/key_io \
|
test/fuzz/key_io \
|
||||||
test/fuzz/key_origin_info_deserialize \
|
test/fuzz/key_origin_info_deserialize \
|
||||||
test/fuzz/kitchen_sink \
|
test/fuzz/kitchen_sink \
|
||||||
|
test/fuzz/load_external_block_file \
|
||||||
test/fuzz/locale \
|
test/fuzz/locale \
|
||||||
test/fuzz/merkle_block_deserialize \
|
test/fuzz/merkle_block_deserialize \
|
||||||
test/fuzz/merkleblock \
|
test/fuzz/merkleblock \
|
||||||
|
@ -80,6 +83,7 @@ FUZZ_TARGETS = \
|
||||||
test/fuzz/partial_merkle_tree_deserialize \
|
test/fuzz/partial_merkle_tree_deserialize \
|
||||||
test/fuzz/partially_signed_transaction_deserialize \
|
test/fuzz/partially_signed_transaction_deserialize \
|
||||||
test/fuzz/policy_estimator \
|
test/fuzz/policy_estimator \
|
||||||
|
test/fuzz/policy_estimator_io \
|
||||||
test/fuzz/pow \
|
test/fuzz/pow \
|
||||||
test/fuzz/prefilled_transaction_deserialize \
|
test/fuzz/prefilled_transaction_deserialize \
|
||||||
test/fuzz/prevector \
|
test/fuzz/prevector \
|
||||||
|
@ -356,6 +360,12 @@ test_fuzz_asmap_direct_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
test_fuzz_asmap_direct_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
test_fuzz_asmap_direct_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
test_fuzz_asmap_direct_SOURCES = test/fuzz/asmap_direct.cpp
|
test_fuzz_asmap_direct_SOURCES = test/fuzz/asmap_direct.cpp
|
||||||
|
|
||||||
|
test_fuzz_autofile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
|
test_fuzz_autofile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
|
test_fuzz_autofile_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
test_fuzz_autofile_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
|
test_fuzz_autofile_SOURCES = test/fuzz/autofile.cpp
|
||||||
|
|
||||||
test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
|
test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
|
||||||
test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
@ -470,6 +480,12 @@ test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
test_fuzz_bloomfilter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
test_fuzz_bloomfilter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
test_fuzz_bloomfilter_deserialize_SOURCES = test/fuzz/deserialize.cpp
|
test_fuzz_bloomfilter_deserialize_SOURCES = test/fuzz/deserialize.cpp
|
||||||
|
|
||||||
|
test_fuzz_buffered_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
|
test_fuzz_buffered_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
|
test_fuzz_buffered_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
test_fuzz_buffered_file_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
|
test_fuzz_buffered_file_SOURCES = test/fuzz/buffered_file.cpp
|
||||||
|
|
||||||
test_fuzz_chain_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
test_fuzz_chain_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
test_fuzz_chain_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
test_fuzz_chain_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
@ -662,6 +678,12 @@ test_fuzz_kitchen_sink_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
test_fuzz_kitchen_sink_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
test_fuzz_kitchen_sink_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
test_fuzz_kitchen_sink_SOURCES = test/fuzz/kitchen_sink.cpp
|
test_fuzz_kitchen_sink_SOURCES = test/fuzz/kitchen_sink.cpp
|
||||||
|
|
||||||
|
test_fuzz_load_external_block_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
|
test_fuzz_load_external_block_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
|
test_fuzz_load_external_block_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
test_fuzz_load_external_block_file_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
|
test_fuzz_load_external_block_file_SOURCES = test/fuzz/load_external_block_file.cpp
|
||||||
|
|
||||||
test_fuzz_locale_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
test_fuzz_locale_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
test_fuzz_locale_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
test_fuzz_locale_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
test_fuzz_locale_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
test_fuzz_locale_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
@ -782,6 +804,12 @@ test_fuzz_policy_estimator_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
test_fuzz_policy_estimator_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
test_fuzz_policy_estimator_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.cpp
|
test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.cpp
|
||||||
|
|
||||||
|
test_fuzz_policy_estimator_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
|
test_fuzz_policy_estimator_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
|
test_fuzz_policy_estimator_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
test_fuzz_policy_estimator_io_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
|
test_fuzz_policy_estimator_io_SOURCES = test/fuzz/policy_estimator_io.cpp
|
||||||
|
|
||||||
test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||||
test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||||
|
|
72
src/test/fuzz/autofile.cpp
Normal file
72
src/test/fuzz/autofile.cpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright (c) 2020 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <optional.h>
|
||||||
|
#include <streams.h>
|
||||||
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
|
#include <test/fuzz/fuzz.h>
|
||||||
|
#include <test/fuzz/util.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||||
|
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
|
||||||
|
CAutoFile auto_file = fuzzed_auto_file_provider.open();
|
||||||
|
while (fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 5)) {
|
||||||
|
case 0: {
|
||||||
|
std::array<uint8_t, 4096> arr{};
|
||||||
|
try {
|
||||||
|
auto_file.read((char*)arr.data(), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
const std::array<uint8_t, 4096> arr{};
|
||||||
|
try {
|
||||||
|
auto_file.write((const char*)arr.data(), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
try {
|
||||||
|
auto_file.ignore(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
auto_file.fclose();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
ReadFromStream(fuzzed_data_provider, auto_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
WriteToStream(fuzzed_data_provider, auto_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void)auto_file.Get();
|
||||||
|
(void)auto_file.GetType();
|
||||||
|
(void)auto_file.GetVersion();
|
||||||
|
(void)auto_file.IsNull();
|
||||||
|
if (fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
FILE* f = auto_file.release();
|
||||||
|
if (f != nullptr) {
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
src/test/fuzz/buffered_file.cpp
Normal file
78
src/test/fuzz/buffered_file.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (c) 2020 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <optional.h>
|
||||||
|
#include <streams.h>
|
||||||
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
|
#include <test/fuzz/fuzz.h>
|
||||||
|
#include <test/fuzz/util.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||||
|
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
|
||||||
|
std::optional<CBufferedFile> opt_buffered_file;
|
||||||
|
FILE* fuzzed_file = fuzzed_file_provider.open();
|
||||||
|
try {
|
||||||
|
opt_buffered_file.emplace(fuzzed_file, fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096), fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<int>());
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
if (fuzzed_file != nullptr) {
|
||||||
|
fclose(fuzzed_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opt_buffered_file && fuzzed_file != nullptr) {
|
||||||
|
bool setpos_fail = false;
|
||||||
|
while (fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 5)) {
|
||||||
|
case 0: {
|
||||||
|
std::array<uint8_t, 4096> arr{};
|
||||||
|
try {
|
||||||
|
opt_buffered_file->read((char*)arr.data(), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
opt_buffered_file->Seek(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
opt_buffered_file->SetLimit(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
if (!opt_buffered_file->SetPos(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096))) {
|
||||||
|
setpos_fail = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
if (setpos_fail) {
|
||||||
|
// Calling FindByte(...) after a failed SetPos(...) call may result in an infinite loop.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
opt_buffered_file->FindByte(fuzzed_data_provider.ConsumeIntegral<char>());
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
ReadFromStream(fuzzed_data_provider, *opt_buffered_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt_buffered_file->GetPos();
|
||||||
|
opt_buffered_file->GetType();
|
||||||
|
opt_buffered_file->GetVersion();
|
||||||
|
}
|
||||||
|
}
|
31
src/test/fuzz/load_external_block_file.cpp
Normal file
31
src/test/fuzz/load_external_block_file.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2020 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <chainparams.h>
|
||||||
|
#include <flatfile.h>
|
||||||
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
|
#include <test/fuzz/fuzz.h>
|
||||||
|
#include <test/fuzz/util.h>
|
||||||
|
#include <test/util/setup_common.h>
|
||||||
|
#include <validation.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
InitializeFuzzingContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||||
|
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
|
||||||
|
FILE* fuzzed_block_file = fuzzed_file_provider.open();
|
||||||
|
if (fuzzed_block_file == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FlatFilePos flat_file_pos;
|
||||||
|
LoadExternalBlockFile(Params(), fuzzed_block_file, fuzzed_data_provider.ConsumeBool() ? &flat_file_pos : nullptr);
|
||||||
|
}
|
|
@ -14,6 +14,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
InitializeFuzzingContext();
|
||||||
|
}
|
||||||
|
|
||||||
void test_one_input(const std::vector<uint8_t>& buffer)
|
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
{
|
{
|
||||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||||
|
@ -66,4 +71,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
(void)block_policy_estimator.estimateSmartFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr, fuzzed_data_provider.ConsumeBool());
|
(void)block_policy_estimator.estimateSmartFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr, fuzzed_data_provider.ConsumeBool());
|
||||||
(void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}));
|
(void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
|
||||||
|
CAutoFile fuzzed_auto_file = fuzzed_auto_file_provider.open();
|
||||||
|
block_policy_estimator.Write(fuzzed_auto_file);
|
||||||
|
block_policy_estimator.Read(fuzzed_auto_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
28
src/test/fuzz/policy_estimator_io.cpp
Normal file
28
src/test/fuzz/policy_estimator_io.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) 2020 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <policy/fees.h>
|
||||||
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
|
#include <test/fuzz/fuzz.h>
|
||||||
|
#include <test/fuzz/util.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
InitializeFuzzingContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||||
|
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
|
||||||
|
CAutoFile fuzzed_auto_file = fuzzed_auto_file_provider.open();
|
||||||
|
// Re-using block_policy_estimator across runs to avoid costly creation of CBlockPolicyEstimator object.
|
||||||
|
static CBlockPolicyEstimator block_policy_estimator;
|
||||||
|
if (block_policy_estimator.Read(fuzzed_auto_file)) {
|
||||||
|
block_policy_estimator.Write(fuzzed_auto_file);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -264,4 +265,209 @@ void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::
|
||||||
static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};
|
static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FuzzedFileProvider
|
||||||
|
{
|
||||||
|
FuzzedDataProvider& m_fuzzed_data_provider;
|
||||||
|
int64_t m_offset = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FuzzedFileProvider(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider{fuzzed_data_provider}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* open()
|
||||||
|
{
|
||||||
|
if (m_fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
std::string mode;
|
||||||
|
switch (m_fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 5)) {
|
||||||
|
case 0: {
|
||||||
|
mode = "r";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
mode = "r+";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
mode = "w";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
mode = "w+";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
mode = "a";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
mode = "a+";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef _GNU_SOURCE
|
||||||
|
const cookie_io_functions_t io_hooks = {
|
||||||
|
FuzzedFileProvider::read,
|
||||||
|
FuzzedFileProvider::write,
|
||||||
|
FuzzedFileProvider::seek,
|
||||||
|
FuzzedFileProvider::close,
|
||||||
|
};
|
||||||
|
return fopencookie(this, mode.c_str(), io_hooks);
|
||||||
|
#else
|
||||||
|
(void)mode;
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read(void* cookie, char* buf, size_t size)
|
||||||
|
{
|
||||||
|
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||||
|
if (buf == nullptr || size == 0 || fuzzed_file->m_fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||||
|
}
|
||||||
|
const std::vector<uint8_t> random_bytes = fuzzed_file->m_fuzzed_data_provider.ConsumeBytes<uint8_t>(size);
|
||||||
|
if (random_bytes.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::memcpy(buf, random_bytes.data(), random_bytes.size());
|
||||||
|
if (AdditionOverflow((uint64_t)fuzzed_file->m_offset, random_bytes.size())) {
|
||||||
|
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||||
|
}
|
||||||
|
fuzzed_file->m_offset += random_bytes.size();
|
||||||
|
return random_bytes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t write(void* cookie, const char* buf, size_t size)
|
||||||
|
{
|
||||||
|
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||||
|
const ssize_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<ssize_t>(0, size);
|
||||||
|
if (AdditionOverflow(fuzzed_file->m_offset, n)) {
|
||||||
|
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||||
|
}
|
||||||
|
fuzzed_file->m_offset += n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seek(void* cookie, int64_t* offset, int whence)
|
||||||
|
{
|
||||||
|
assert(whence == SEEK_SET || whence == SEEK_CUR); // SEEK_END not implemented yet.
|
||||||
|
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||||
|
int64_t new_offset = 0;
|
||||||
|
if (whence == SEEK_SET) {
|
||||||
|
new_offset = *offset;
|
||||||
|
} else if (whence == SEEK_CUR) {
|
||||||
|
if (AdditionOverflow(fuzzed_file->m_offset, *offset)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
new_offset = fuzzed_file->m_offset + *offset;
|
||||||
|
}
|
||||||
|
if (new_offset < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fuzzed_file->m_offset = new_offset;
|
||||||
|
*offset = new_offset;
|
||||||
|
return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(-1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close(void* cookie)
|
||||||
|
{
|
||||||
|
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||||
|
return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(-1, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NODISCARD inline FuzzedFileProvider ConsumeFile(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||||
|
{
|
||||||
|
return {fuzzed_data_provider};
|
||||||
|
}
|
||||||
|
|
||||||
|
class FuzzedAutoFileProvider
|
||||||
|
{
|
||||||
|
FuzzedDataProvider& m_fuzzed_data_provider;
|
||||||
|
FuzzedFileProvider m_fuzzed_file_provider;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FuzzedAutoFileProvider(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider{fuzzed_data_provider}, m_fuzzed_file_provider{fuzzed_data_provider}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CAutoFile open()
|
||||||
|
{
|
||||||
|
return {m_fuzzed_file_provider.open(), m_fuzzed_data_provider.ConsumeIntegral<int>(), m_fuzzed_data_provider.ConsumeIntegral<int>()};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NODISCARD inline FuzzedAutoFileProvider ConsumeAutoFile(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||||
|
{
|
||||||
|
return {fuzzed_data_provider};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WRITE_TO_STREAM_CASE(id, type, consume) \
|
||||||
|
case id: { \
|
||||||
|
type o = consume; \
|
||||||
|
stream << o; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
template <typename Stream>
|
||||||
|
void WriteToStream(FuzzedDataProvider& fuzzed_data_provider, Stream& stream) noexcept
|
||||||
|
{
|
||||||
|
while (fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
try {
|
||||||
|
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 13)) {
|
||||||
|
WRITE_TO_STREAM_CASE(0, bool, fuzzed_data_provider.ConsumeBool())
|
||||||
|
WRITE_TO_STREAM_CASE(1, char, fuzzed_data_provider.ConsumeIntegral<char>())
|
||||||
|
WRITE_TO_STREAM_CASE(2, int8_t, fuzzed_data_provider.ConsumeIntegral<int8_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(3, uint8_t, fuzzed_data_provider.ConsumeIntegral<uint8_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(4, int16_t, fuzzed_data_provider.ConsumeIntegral<int16_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(5, uint16_t, fuzzed_data_provider.ConsumeIntegral<uint16_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(6, int32_t, fuzzed_data_provider.ConsumeIntegral<int32_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(7, uint32_t, fuzzed_data_provider.ConsumeIntegral<uint32_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(8, int64_t, fuzzed_data_provider.ConsumeIntegral<int64_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(9, uint64_t, fuzzed_data_provider.ConsumeIntegral<uint64_t>())
|
||||||
|
WRITE_TO_STREAM_CASE(10, float, fuzzed_data_provider.ConsumeFloatingPoint<float>())
|
||||||
|
WRITE_TO_STREAM_CASE(11, double, fuzzed_data_provider.ConsumeFloatingPoint<double>())
|
||||||
|
WRITE_TO_STREAM_CASE(12, std::string, fuzzed_data_provider.ConsumeRandomLengthString(32))
|
||||||
|
WRITE_TO_STREAM_CASE(13, std::vector<char>, ConsumeRandomLengthIntegralVector<char>(fuzzed_data_provider))
|
||||||
|
}
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_FROM_STREAM_CASE(id, type) \
|
||||||
|
case id: { \
|
||||||
|
type o; \
|
||||||
|
stream >> o; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
template <typename Stream>
|
||||||
|
void ReadFromStream(FuzzedDataProvider& fuzzed_data_provider, Stream& stream) noexcept
|
||||||
|
{
|
||||||
|
while (fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
try {
|
||||||
|
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 13)) {
|
||||||
|
READ_FROM_STREAM_CASE(0, bool)
|
||||||
|
READ_FROM_STREAM_CASE(1, char)
|
||||||
|
READ_FROM_STREAM_CASE(2, int8_t)
|
||||||
|
READ_FROM_STREAM_CASE(3, uint8_t)
|
||||||
|
READ_FROM_STREAM_CASE(4, int16_t)
|
||||||
|
READ_FROM_STREAM_CASE(5, uint16_t)
|
||||||
|
READ_FROM_STREAM_CASE(6, int32_t)
|
||||||
|
READ_FROM_STREAM_CASE(7, uint32_t)
|
||||||
|
READ_FROM_STREAM_CASE(8, int64_t)
|
||||||
|
READ_FROM_STREAM_CASE(9, uint64_t)
|
||||||
|
READ_FROM_STREAM_CASE(10, float)
|
||||||
|
READ_FROM_STREAM_CASE(11, double)
|
||||||
|
READ_FROM_STREAM_CASE(12, std::string)
|
||||||
|
READ_FROM_STREAM_CASE(13, std::vector<char>)
|
||||||
|
}
|
||||||
|
} catch (const std::ios_base::failure&) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BITCOIN_TEST_FUZZ_UTIL_H
|
#endif // BITCOIN_TEST_FUZZ_UTIL_H
|
||||||
|
|
Loading…
Reference in a new issue