Coverage Report

Created: 2026-04-20 22:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/test/fuzz/overflow.cpp
Line
Count
Source
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
396
{
19
396
    constexpr auto min{std::numeric_limits<T>::min()};
20
396
    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
396
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
396
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
2.37k
    auto widen = [](T value) -> W { return value; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIalEEvR18FuzzedDataProviderENKUlaE_clEa
Line
Count
Source
25
396
    auto widen = [](T value) -> W { return value; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIslEEvR18FuzzedDataProviderENKUlsE_clEs
Line
Count
Source
25
396
    auto widen = [](T value) -> W { return value; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIilEEvR18FuzzedDataProviderENKUliE_clEi
Line
Count
Source
25
396
    auto widen = [](T value) -> W { return value; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIhmEEvR18FuzzedDataProviderENKUlhE_clEh
Line
Count
Source
25
396
    auto widen = [](T value) -> W { return value; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowItmEEvR18FuzzedDataProviderENKUltE_clEt
Line
Count
Source
25
396
    auto widen = [](T value) -> W { return value; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIjmEEvR18FuzzedDataProviderENKUljE_clEj
Line
Count
Source
25
396
    auto widen = [](T value) -> W { return value; };
26
792
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIalEEvR18FuzzedDataProviderENKUllE_clEl
Line
Count
Source
26
132
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIslEEvR18FuzzedDataProviderENKUllE_clEl
Line
Count
Source
26
132
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIilEEvR18FuzzedDataProviderENKUllE_clEl
Line
Count
Source
26
132
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIhmEEvR18FuzzedDataProviderENKUlmE_clEm
Line
Count
Source
26
132
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowItmEEvR18FuzzedDataProviderENKUlmE_clEm
Line
Count
Source
26
132
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIjmEEvR18FuzzedDataProviderENKUlmE_clEm
Line
Count
Source
26
132
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
792
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIalEEvR18FuzzedDataProviderENKUllE0_clEl
Line
Count
Source
27
132
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIslEEvR18FuzzedDataProviderENKUllE0_clEl
Line
Count
Source
27
132
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIilEEvR18FuzzedDataProviderENKUllE0_clEl
Line
Count
Source
27
132
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIhmEEvR18FuzzedDataProviderENKUlmE0_clEm
Line
Count
Source
27
132
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowItmEEvR18FuzzedDataProviderENKUlmE0_clEm
Line
Count
Source
27
132
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
overflow.cpp:_ZZN12_GLOBAL__N_112TestOverflowIjmEEvR18FuzzedDataProviderENKUlmE0_clEm
Line
Count
Source
27
132
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
396
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
396
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
396
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
396
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
396
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
396
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
396
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
396
}
overflow.cpp:_ZN12_GLOBAL__N_112TestOverflowIalEEvR18FuzzedDataProvider
Line
Count
Source
18
66
{
19
66
    constexpr auto min{std::numeric_limits<T>::min()};
20
66
    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
66
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
66
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
66
    auto widen = [](T value) -> W { return value; };
26
66
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
66
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
66
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
66
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
66
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
66
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
66
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
66
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
66
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
66
}
overflow.cpp:_ZN12_GLOBAL__N_112TestOverflowIslEEvR18FuzzedDataProvider
Line
Count
Source
18
66
{
19
66
    constexpr auto min{std::numeric_limits<T>::min()};
20
66
    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
66
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
66
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
66
    auto widen = [](T value) -> W { return value; };
26
66
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
66
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
66
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
66
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
66
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
66
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
66
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
66
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
66
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
66
}
overflow.cpp:_ZN12_GLOBAL__N_112TestOverflowIilEEvR18FuzzedDataProvider
Line
Count
Source
18
66
{
19
66
    constexpr auto min{std::numeric_limits<T>::min()};
20
66
    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
66
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
66
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
66
    auto widen = [](T value) -> W { return value; };
26
66
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
66
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
66
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
66
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
66
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
66
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
66
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
66
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
66
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
66
}
overflow.cpp:_ZN12_GLOBAL__N_112TestOverflowIhmEEvR18FuzzedDataProvider
Line
Count
Source
18
66
{
19
66
    constexpr auto min{std::numeric_limits<T>::min()};
20
66
    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
66
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
66
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
66
    auto widen = [](T value) -> W { return value; };
26
66
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
66
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
66
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
66
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
66
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
66
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
66
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
66
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
66
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
66
}
overflow.cpp:_ZN12_GLOBAL__N_112TestOverflowItmEEvR18FuzzedDataProvider
Line
Count
Source
18
66
{
19
66
    constexpr auto min{std::numeric_limits<T>::min()};
20
66
    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
66
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
66
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
66
    auto widen = [](T value) -> W { return value; };
26
66
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
66
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
66
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
66
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
66
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
66
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
66
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
66
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
66
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
66
}
overflow.cpp:_ZN12_GLOBAL__N_112TestOverflowIjmEEvR18FuzzedDataProvider
Line
Count
Source
18
66
{
19
66
    constexpr auto min{std::numeric_limits<T>::min()};
20
66
    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
66
    static_assert(min >= std::numeric_limits<W>::min() / 2);
23
66
    static_assert(max <= std::numeric_limits<W>::max() / 2);
24
25
66
    auto widen = [](T value) -> W { return value; };
26
66
    auto clamp = [](W value) -> W { return std::clamp<W>(value, min, max); };
27
66
    auto check = [](W value) -> std::optional<W> { if (value >= min && value <= max) return value; else return std::nullopt; };
28
29
66
    const T i = fuzzed_data_provider.ConsumeIntegral<T>();
30
66
    const T j = fuzzed_data_provider.ConsumeIntegral<T>();
31
66
    const unsigned shift = fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, std::numeric_limits<W>::digits - std::numeric_limits<T>::digits);
32
33
66
    Assert(clamp(widen(i) + widen(j)) == SaturatingAdd(i, j));
34
66
    Assert(check(widen(i) + widen(j)) == CheckedAdd(i, j));
35
36
66
    Assert(clamp(widen(i) << shift) == SaturatingLeftShift(i, shift));
37
66
    Assert(check(widen(i) << shift) == CheckedLeftShift(i, shift));
38
66
}
39
} // namespace
40
41
FUZZ_TARGET(overflow)
42
66
{
43
66
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
44
66
    TestOverflow<int8_t, int64_t>(fuzzed_data_provider);
45
66
    TestOverflow<int16_t, int64_t>(fuzzed_data_provider);
46
66
    TestOverflow<int32_t, int64_t>(fuzzed_data_provider);
47
66
    TestOverflow<uint8_t, uint64_t>(fuzzed_data_provider);
48
66
    TestOverflow<uint16_t, uint64_t>(fuzzed_data_provider);
49
66
    TestOverflow<uint32_t, uint64_t>(fuzzed_data_provider);
50
66
}