// Copyright (c) 2025-present 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 namespace { //! Test overflow operations for type T using a wider type, W, to verify results. template void TestOverflow(FuzzedDataProvider& fuzzed_data_provider) { constexpr auto min{std::numeric_limits::min()}; constexpr auto max{std::numeric_limits::max()}; // Range needs to be at least twice as big to allow two numbers to be added without overflowing. static_assert(min >= std::numeric_limits::min() / 2); static_assert(max <= std::numeric_limits::max() / 2); auto widen = [](T value) -> W { return value; }; auto clamp = [](W value) -> W { return std::clamp(value, min, max); }; auto check = [](W value) -> std::optional { if (value >= min && value <= max) return value; else return std::nullopt; }; const T i = fuzzed_data_provider.ConsumeIntegral(); const T j = fuzzed_data_provider.ConsumeIntegral(); const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits::digits - std::numeric_limits::digits); Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j)); Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j)); Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift)); Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift)); } } // namespace FUZZ_TARGET(overflow) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); TestOverflow(fuzzed_data_provider); TestOverflow(fuzzed_data_provider); TestOverflow(fuzzed_data_provider); TestOverflow(fuzzed_data_provider); TestOverflow(fuzzed_data_provider); TestOverflow(fuzzed_data_provider); }