From 44fb2a596b4a1aa70253c4145c35be6de68da22a Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 7 Apr 2020 15:40:13 +0000 Subject: [PATCH 1/6] tests: Add fuzzing harness for FeeFilterRounder --- src/Makefile.test.include | 7 +++++++ src/test/fuzz/fees.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/fuzz/fees.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c3021743f41..70bb3852981 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -34,6 +34,7 @@ FUZZ_TARGETS = \ test/fuzz/eval_script \ test/fuzz/fee_rate \ test/fuzz/fee_rate_deserialize \ + test/fuzz/fees \ test/fuzz/flat_file_pos_deserialize \ test/fuzz/flatfile \ test/fuzz/float \ @@ -465,6 +466,12 @@ test_fuzz_fee_rate_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_fee_rate_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_fee_rate_deserialize_SOURCES = test/fuzz/deserialize.cpp +test_fuzz_fees_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_fees_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_fees_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_fees_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_fees_SOURCES = test/fuzz/fees.cpp + test_fuzz_flat_file_pos_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFLAT_FILE_POS_DESERIALIZE=1 test_fuzz_flat_file_pos_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_flat_file_pos_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp new file mode 100644 index 00000000000..090994263ea --- /dev/null +++ b/src/test/fuzz/fees.cpp @@ -0,0 +1,26 @@ +// 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +void test_one_input(const std::vector& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)}; + FeeFilterRounder fee_filter_rounder{minimal_incremental_fee}; + while (fuzzed_data_provider.ConsumeBool()) { + const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider); + const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee); + assert(MoneyRange(rounded_fee)); + } +} From 7b9a2dc86426926038b2f49d3d4ce4cb64dcd14b Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 7 Apr 2020 16:31:43 +0000 Subject: [PATCH 2/6] tests: Add fuzzing harness for AdditionOverflow(...) --- src/Makefile.test.include | 7 ++++ src/test/fuzz/addition_overflow.cpp | 55 +++++++++++++++++++++++++++++ src/test/fuzz/util.h | 11 ++++++ 3 files changed, 73 insertions(+) create mode 100644 src/test/fuzz/addition_overflow.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 70bb3852981..1f1d70d9cdd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -3,6 +3,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. FUZZ_TARGETS = \ + test/fuzz/addition_overflow \ test/fuzz/addr_info_deserialize \ test/fuzz/addrdb \ test/fuzz/address_deserialize \ @@ -280,6 +281,12 @@ endif if ENABLE_FUZZ +test_fuzz_addition_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_addition_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_addition_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_addition_overflow_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_addition_overflow_SOURCES = test/fuzz/addition_overflow.cpp + test_fuzz_addr_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDR_INFO_DESERIALIZE=1 test_fuzz_addr_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_addr_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp new file mode 100644 index 00000000000..a455992b137 --- /dev/null +++ b/src/test/fuzz/addition_overflow.cpp @@ -0,0 +1,55 @@ +// 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 +#include +#include + +#include +#include +#include + +#if defined(__has_builtin) +#if __has_builtin(__builtin_add_overflow) +#define HAVE_BUILTIN_ADD_OVERFLOW +#endif +#elif defined(__GNUC__) && (__GNUC__ >= 5) +#define HAVE_BUILTIN_ADD_OVERFLOW +#endif + +namespace { +template +void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider) +{ + const T i = fuzzed_data_provider.ConsumeIntegral(); + const T j = fuzzed_data_provider.ConsumeIntegral(); + const bool is_addition_overflow_custom = AdditionOverflow(i, j); +#if defined(HAVE_BUILTIN_ADD_OVERFLOW) + T result_builtin; + const bool is_addition_overflow_builtin = __builtin_add_overflow(i, j, &result_builtin); + assert(is_addition_overflow_custom == is_addition_overflow_builtin); + if (!is_addition_overflow_custom) { + assert(i + j == result_builtin); + } +#else + if (!is_addition_overflow_custom) { + (void)(i + j); + } +#endif +} +} // namespace + +void test_one_input(const std::vector& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); + TestAdditionOverflow(fuzzed_data_provider); +} diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index b70ea6d90e2..ba4b012f95a 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -120,4 +120,15 @@ NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept } } +template +NODISCARD bool AdditionOverflow(const T i, const T j) noexcept +{ + static_assert(std::is_integral::value, "Integral required."); + if (std::numeric_limits::is_signed) { + return (i > 0 && j > std::numeric_limits::max() - i) || + (i < 0 && j < std::numeric_limits::min() - i); + } + return std::numeric_limits::max() - i < j; +} + #endif // BITCOIN_TEST_FUZZ_UTIL_H From 2df5701e902effa93834d9520690cbaca7e504f3 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 7 Apr 2020 16:32:00 +0000 Subject: [PATCH 3/6] tests: Add coverage of GetVirtualTransactionSize(...) to existing fuzzer --- src/test/fuzz/integer.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp index fff2fabd178..f3259f65987 100644 --- a/src/test/fuzz/integer.cpp +++ b/src/test/fuzz/integer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -90,8 +91,12 @@ void test_one_input(const std::vector& buffer) } (void)GetSizeOfCompactSize(u64); (void)GetSpecialScriptSize(u32); - // (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs - // (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs + if (!MultiplicationOverflow(i64, static_cast(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast(4))) { + (void)GetVirtualTransactionSize(i64, i64); + } + if (!MultiplicationOverflow(i64, static_cast(u32)) && !AdditionOverflow(i64, static_cast(4)) && !AdditionOverflow(i64 * u32, static_cast(4))) { + (void)GetVirtualTransactionSize(i64, i64, u32); + } (void)HexDigit(ch); (void)MoneyRange(i64); (void)ToString(i64); From 57890b2555ca347373109052f6789c23f46bc594 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Wed, 8 Apr 2020 13:16:04 +0000 Subject: [PATCH 4/6] tests: Add fuzzing harness for classes/functions in checkqueue.h --- src/Makefile.test.include | 7 ++++ src/test/fuzz/checkqueue.cpp | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/test/fuzz/checkqueue.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1f1d70d9cdd..2a1f1ea73b5 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -28,6 +28,7 @@ FUZZ_TARGETS = \ test/fuzz/bloom_filter \ test/fuzz/bloomfilter_deserialize \ test/fuzz/chain \ + test/fuzz/checkqueue \ test/fuzz/coins_deserialize \ test/fuzz/decode_tx \ test/fuzz/descriptor_parse \ @@ -431,6 +432,12 @@ test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_chain_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_chain_SOURCES = test/fuzz/chain.cpp +test_fuzz_checkqueue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_checkqueue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_checkqueue_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_checkqueue_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_checkqueue_SOURCES = test/fuzz/checkqueue.cpp + test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1 test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/test/fuzz/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp new file mode 100644 index 00000000000..2ed097b8275 --- /dev/null +++ b/src/test/fuzz/checkqueue.cpp @@ -0,0 +1,65 @@ +// 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 +#include +#include +#include +#include + +#include +#include +#include + +namespace { +struct DumbCheck { + const bool result = false; + + DumbCheck() = default; + + explicit DumbCheck(const bool _result) : result(_result) + { + } + + bool operator()() const + { + return result; + } + + void swap(DumbCheck& x) + { + } +}; +} // namespace + +void test_one_input(const std::vector& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + const unsigned int batch_size = fuzzed_data_provider.ConsumeIntegralInRange(0, 1024); + CCheckQueue check_queue_1{batch_size}; + CCheckQueue check_queue_2{batch_size}; + std::vector checks_1; + std::vector checks_2; + const int size = fuzzed_data_provider.ConsumeIntegralInRange(0, 1024); + for (int i = 0; i < size; ++i) { + const bool result = fuzzed_data_provider.ConsumeBool(); + checks_1.emplace_back(result); + checks_2.emplace_back(result); + } + if (fuzzed_data_provider.ConsumeBool()) { + check_queue_1.Add(checks_1); + } + if (fuzzed_data_provider.ConsumeBool()) { + (void)check_queue_1.Wait(); + } + + CCheckQueueControl check_queue_control{&check_queue_2}; + if (fuzzed_data_provider.ConsumeBool()) { + check_queue_control.Add(checks_2); + } + if (fuzzed_data_provider.ConsumeBool()) { + (void)check_queue_control.Wait(); + } +} From bf76000493082da05bf7258a5038e16fa76cd143 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Wed, 8 Apr 2020 13:48:37 +0000 Subject: [PATCH 5/6] tests: Add fuzzing harness for classes/functions in cuckoocache.h --- src/Makefile.test.include | 7 +++++ src/cuckoocache.h | 1 + src/test/fuzz/cuckoocache.cpp | 49 +++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/test/fuzz/cuckoocache.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 2a1f1ea73b5..fa0fbca8e84 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -30,6 +30,7 @@ FUZZ_TARGETS = \ test/fuzz/chain \ test/fuzz/checkqueue \ test/fuzz/coins_deserialize \ + test/fuzz/cuckoocache \ test/fuzz/decode_tx \ test/fuzz/descriptor_parse \ test/fuzz/diskblockindex_deserialize \ @@ -444,6 +445,12 @@ test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_coins_deserialize_SOURCES = test/fuzz/deserialize.cpp +test_fuzz_cuckoocache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_cuckoocache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_cuckoocache_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_cuckoocache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_cuckoocache_SOURCES = test/fuzz/cuckoocache.cpp + test_fuzz_decode_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_fuzz_decode_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_decode_tx_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/cuckoocache.h b/src/cuckoocache.h index 4ad5818cdc1..2daf676c4a6 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_CUCKOOCACHE_H #define BITCOIN_CUCKOOCACHE_H +#include // std::find #include #include #include diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp new file mode 100644 index 00000000000..f674efe1b12 --- /dev/null +++ b/src/test/fuzz/cuckoocache.cpp @@ -0,0 +1,49 @@ +// 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 +#include +#include