diff options
-rw-r--r-- | src/Makefile.test.include | 7 | ||||
-rw-r--r-- | src/test/fuzz/addition_overflow.cpp | 55 | ||||
-rw-r--r-- | src/test/fuzz/util.h | 11 |
3 files changed, 73 insertions, 0 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 70bb385298..1f1d70d9cd 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 0000000000..a455992b13 --- /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 <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <string> +#include <vector> + +#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 <typename T> +void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider) +{ + const T i = fuzzed_data_provider.ConsumeIntegral<T>(); + const T j = fuzzed_data_provider.ConsumeIntegral<T>(); + 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<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + TestAdditionOverflow<int64_t>(fuzzed_data_provider); + TestAdditionOverflow<uint64_t>(fuzzed_data_provider); + TestAdditionOverflow<int32_t>(fuzzed_data_provider); + TestAdditionOverflow<uint32_t>(fuzzed_data_provider); + TestAdditionOverflow<int16_t>(fuzzed_data_provider); + TestAdditionOverflow<uint16_t>(fuzzed_data_provider); + TestAdditionOverflow<char>(fuzzed_data_provider); + TestAdditionOverflow<unsigned char>(fuzzed_data_provider); + TestAdditionOverflow<signed char>(fuzzed_data_provider); +} diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index b70ea6d90e..ba4b012f95 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 <class T> +NODISCARD bool AdditionOverflow(const T i, const T j) noexcept +{ + static_assert(std::is_integral<T>::value, "Integral required."); + if (std::numeric_limits<T>::is_signed) { + return (i > 0 && j > std::numeric_limits<T>::max() - i) || + (i < 0 && j < std::numeric_limits<T>::min() - i); + } + return std::numeric_limits<T>::max() - i < j; +} + #endif // BITCOIN_TEST_FUZZ_UTIL_H |