Bitcoin Core Fuzz Coverage Report

Coverage Report

Created: 2026-05-28 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/brunogarcia/projects/bitcoin-core-dev/src/util/overflow.h
Line
Count
Source
1
// Copyright (c) 2021-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
#ifndef BITCOIN_UTIL_OVERFLOW_H
6
#define BITCOIN_UTIL_OVERFLOW_H
7
8
#include <util/check.h>
9
10
#include <climits>
11
#include <concepts>
12
#include <limits>
13
#include <optional>
14
#include <type_traits>
15
16
template <class T>
17
[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept
18
98.5k
{
19
98.5k
    static_assert(std::is_integral_v<T>, "Integral required.");
20
98.5k
    if constexpr (std::numeric_limits<T>::is_signed) {
21
0
        return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
22
0
               (i < 0 && j < std::numeric_limits<T>::min() - i);
23
0
    }
24
0
    return std::numeric_limits<T>::max() - i < j;
25
98.5k
}
Unexecuted instantiation: bool AdditionOverflow<long long>(long long, long long)
Unexecuted instantiation: bool AdditionOverflow<unsigned long long>(unsigned long long, unsigned long long)
Unexecuted instantiation: bool AdditionOverflow<int>(int, int)
Unexecuted instantiation: bool AdditionOverflow<unsigned int>(unsigned int, unsigned int)
Unexecuted instantiation: bool AdditionOverflow<short>(short, short)
Unexecuted instantiation: bool AdditionOverflow<unsigned short>(unsigned short, unsigned short)
Unexecuted instantiation: bool AdditionOverflow<char>(char, char)
Unexecuted instantiation: bool AdditionOverflow<unsigned char>(unsigned char, unsigned char)
Unexecuted instantiation: bool AdditionOverflow<signed char>(signed char, signed char)
bool AdditionOverflow<unsigned long>(unsigned long, unsigned long)
Line
Count
Source
18
98.5k
{
19
98.5k
    static_assert(std::is_integral_v<T>, "Integral required.");
20
    if constexpr (std::numeric_limits<T>::is_signed) {
21
        return (i > 0 && j > std::numeric_limits<T>::max() - i) ||
22
               (i < 0 && j < std::numeric_limits<T>::min() - i);
23
    }
24
98.5k
    return std::numeric_limits<T>::max() - i < j;
25
98.5k
}
26
27
template <class T>
28
[[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept
29
98.5k
{
30
98.5k
    if (AdditionOverflow(i, j)) {
31
0
        return std::nullopt;
32
0
    }
33
98.5k
    return i + j;
34
98.5k
}
Unexecuted instantiation: std::__1::optional<long long> CheckedAdd<long long>(long long, long long)
Unexecuted instantiation: std::__1::optional<unsigned long long> CheckedAdd<unsigned long long>(unsigned long long, unsigned long long)
Unexecuted instantiation: std::__1::optional<int> CheckedAdd<int>(int, int)
Unexecuted instantiation: std::__1::optional<unsigned int> CheckedAdd<unsigned int>(unsigned int, unsigned int)
Unexecuted instantiation: std::__1::optional<short> CheckedAdd<short>(short, short)
Unexecuted instantiation: std::__1::optional<unsigned short> CheckedAdd<unsigned short>(unsigned short, unsigned short)
Unexecuted instantiation: std::__1::optional<char> CheckedAdd<char>(char, char)
Unexecuted instantiation: std::__1::optional<unsigned char> CheckedAdd<unsigned char>(unsigned char, unsigned char)
Unexecuted instantiation: std::__1::optional<signed char> CheckedAdd<signed char>(signed char, signed char)
std::__1::optional<unsigned long> CheckedAdd<unsigned long>(unsigned long, unsigned long)
Line
Count
Source
29
98.5k
{
30
98.5k
    if (AdditionOverflow(i, j)) {
31
0
        return std::nullopt;
32
0
    }
33
98.5k
    return i + j;
34
98.5k
}
35
36
template <std::unsigned_integral T, std::unsigned_integral U>
37
[[nodiscard]] constexpr bool TrySub(T& i, const U j) noexcept
38
0
{
39
0
    if (i < T{j}) return false;
40
0
    i -= T{j};
41
0
    return true;
42
0
}
Unexecuted instantiation: bool TrySub<unsigned long, bool>(unsigned long&, bool)
Unexecuted instantiation: bool TrySub<unsigned long, unsigned long>(unsigned long&, unsigned long)
43
44
template <class T>
45
[[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept
46
0
{
47
0
    if constexpr (std::numeric_limits<T>::is_signed) {
48
0
        if (i > 0 && j > std::numeric_limits<T>::max() - i) {
49
0
            return std::numeric_limits<T>::max();
50
0
        }
51
0
        if (i < 0 && j < std::numeric_limits<T>::min() - i) {
52
0
            return std::numeric_limits<T>::min();
53
0
        }
54
0
    } else {
55
0
        if (std::numeric_limits<T>::max() - i < j) {
56
0
            return std::numeric_limits<T>::max();
57
0
        }
58
0
    }
59
0
    return i + j;
60
0
}
Unexecuted instantiation: long long SaturatingAdd<long long>(long long, long long)
Unexecuted instantiation: unsigned long long SaturatingAdd<unsigned long long>(unsigned long long, unsigned long long)
Unexecuted instantiation: int SaturatingAdd<int>(int, int)
Unexecuted instantiation: unsigned int SaturatingAdd<unsigned int>(unsigned int, unsigned int)
Unexecuted instantiation: short SaturatingAdd<short>(short, short)
Unexecuted instantiation: unsigned short SaturatingAdd<unsigned short>(unsigned short, unsigned short)
Unexecuted instantiation: char SaturatingAdd<char>(char, char)
Unexecuted instantiation: unsigned char SaturatingAdd<unsigned char>(unsigned char, unsigned char)
Unexecuted instantiation: signed char SaturatingAdd<signed char>(signed char, signed char)
Unexecuted instantiation: unsigned long SaturatingAdd<unsigned long>(unsigned long, unsigned long)
61
62
/**
63
 * @brief Integer ceiling division (for unsigned values).
64
 *
65
 * Computes the smallest integer q such that q * divisor >= dividend.
66
 * Both dividend and divisor must be unsigned, and divisor must be non-zero.
67
 *
68
 * The implementation avoids overflow that can occur with `(dividend + divisor - 1) / divisor`.
69
 */
70
template <std::unsigned_integral Dividend, std::unsigned_integral Divisor>
71
[[nodiscard]] constexpr auto CeilDiv(const Dividend dividend, const Divisor divisor)
72
2.85k
{
73
2.85k
    assert(divisor > 0);
74
2.85k
    return dividend / divisor + (dividend % divisor != 0);
75
2.85k
}
auto CeilDiv<unsigned long, unsigned int>(unsigned long, unsigned int)
Line
Count
Source
72
608
{
73
608
    assert(divisor > 0);
74
608
    return dividend / divisor + (dividend % divisor != 0);
75
608
}
Unexecuted instantiation: auto CeilDiv<unsigned long, unsigned long>(unsigned long, unsigned long)
Unexecuted instantiation: auto CeilDiv<unsigned long long, unsigned int>(unsigned long long, unsigned int)
Unexecuted instantiation: auto CeilDiv<unsigned int, unsigned long>(unsigned int, unsigned long)
auto CeilDiv<unsigned int, unsigned int>(unsigned int, unsigned int)
Line
Count
Source
72
2.24k
{
73
2.24k
    assert(divisor > 0);
74
2.24k
    return dividend / divisor + (dividend % divisor != 0);
75
2.24k
}
76
77
/**
78
 * @brief Left bit shift with overflow checking.
79
 * @param input The input value to be left shifted.
80
 * @param shift The number of bits to left shift.
81
 * @return (input * 2^shift) or nullopt if it would not fit in the return type.
82
 */
83
template <std::integral T>
84
constexpr std::optional<T> CheckedLeftShift(T input, unsigned shift) noexcept
85
0
{
86
0
    if (shift == 0 || input == 0) return input;
87
    // Avoid undefined c++ behaviour if shift is >= number of bits in T.
88
0
    if (shift >= sizeof(T) * CHAR_BIT) return std::nullopt;
89
    // If input << shift is too big to fit in T, return nullopt.
90
0
    if (input > (std::numeric_limits<T>::max() >> shift)) return std::nullopt;
91
0
    if (input < (std::numeric_limits<T>::min() >> shift)) return std::nullopt;
92
0
    return input << shift;
93
0
}
Unexecuted instantiation: std::__1::optional<unsigned long long> CheckedLeftShift<unsigned long long>(unsigned long long, unsigned int)
Unexecuted instantiation: std::__1::optional<signed char> CheckedLeftShift<signed char>(signed char, unsigned int)
Unexecuted instantiation: std::__1::optional<short> CheckedLeftShift<short>(short, unsigned int)
Unexecuted instantiation: std::__1::optional<int> CheckedLeftShift<int>(int, unsigned int)
Unexecuted instantiation: std::__1::optional<unsigned char> CheckedLeftShift<unsigned char>(unsigned char, unsigned int)
Unexecuted instantiation: std::__1::optional<unsigned short> CheckedLeftShift<unsigned short>(unsigned short, unsigned int)
Unexecuted instantiation: std::__1::optional<unsigned int> CheckedLeftShift<unsigned int>(unsigned int, unsigned int)
94
95
/**
96
 * @brief Left bit shift with safe minimum and maximum values.
97
 * @param input The input value to be left shifted.
98
 * @param shift The number of bits to left shift.
99
 * @return (input * 2^shift) clamped to fit between the lowest and highest
100
 *         representable values of the type T.
101
 */
102
template <std::integral T>
103
constexpr T SaturatingLeftShift(T input, unsigned shift) noexcept
104
0
{
105
0
    if (auto result{CheckedLeftShift(input, shift)}) return *result;
106
    // If input << shift is too big to fit in T, return biggest positive or negative
107
    // number that fits.
108
0
    return input < 0 ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
109
0
}
Unexecuted instantiation: signed char SaturatingLeftShift<signed char>(signed char, unsigned int)
Unexecuted instantiation: short SaturatingLeftShift<short>(short, unsigned int)
Unexecuted instantiation: int SaturatingLeftShift<int>(int, unsigned int)
Unexecuted instantiation: unsigned char SaturatingLeftShift<unsigned char>(unsigned char, unsigned int)
Unexecuted instantiation: unsigned short SaturatingLeftShift<unsigned short>(unsigned short, unsigned int)
Unexecuted instantiation: unsigned int SaturatingLeftShift<unsigned int>(unsigned int, unsigned int)
Unexecuted instantiation: unsigned long long SaturatingLeftShift<unsigned long long>(unsigned long long, unsigned int)
110
111
#endif // BITCOIN_UTIL_OVERFLOW_H