overflow.cpp
1 // Copyright (c) 2025-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <test/fuzz/FuzzedDataProvider.h> 6 #include <test/fuzz/fuzz.h> 7 #include <util/check.h> 8 #include <util/overflow.h> 9 10 #include <algorithm> 11 #include <limits> 12 #include <optional> 13 14 namespace { 15 //! Test overflow operations for type T using a wider type, W, to verify results. 16 template <typename T, typename W> 17 void TestOverflow(FuzzedDataProvider& fuzzed_data_provider) 18 { 19 constexpr auto min{std::numeric_limits<T>::min()}; 20 constexpr auto max{std::numeric_limits<T>::max()}; 21 // Range needs to be at least twice as big to allow two numbers to be added without overflowing. 22 static_assert(min >= std::numeric_limits<W>::min() / 2); 23 static_assert(max <= std::numeric_limits<W>::max() / 2); 24 25 auto widen = [](T value) -> W { return value; }; 26 auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); }; 27 auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; }; 28 29 const T i = fuzzed_data_provider.ConsumeIntegral<T>(); 30 const T j = fuzzed_data_provider.ConsumeIntegral<T>(); 31 const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits); 32 33 Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j)); 34 Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j)); 35 36 Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift)); 37 Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift)); 38 } 39 } // namespace 40 41 FUZZ_TARGET(overflow) 42 { 43 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 44 TestOverflow<int8_t, int64_t>(fuzzed_data_provider); 45 TestOverflow<int16_t, int64_t>(fuzzed_data_provider); 46 TestOverflow<int32_t, int64_t>(fuzzed_data_provider); 47 TestOverflow<uint8_t, uint64_t>(fuzzed_data_provider); 48 TestOverflow<uint16_t, uint64_t>(fuzzed_data_provider); 49 TestOverflow<uint32_t, uint64_t>(fuzzed_data_provider); 50 }