LCOV - code coverage report
Current view: top level - src/util - overflow.h (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 88.9 % 27 24
Test Date: 2026-03-13 04:56:35 Functions: 88.9 % 18 16
Branches: 70.0 % 70 49

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

Generated by: LCOV version 2.0-1