|
| 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 | +} |
0 commit comments