From 7b9a2dc86426926038b2f49d3d4ce4cb64dcd14b Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 7 Apr 2020 16:31:43 +0000 Subject: [PATCH] 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