﻿# V1083\. Signed integer overflow in arithmetic expression\. This leads to undefined behavior\.

The analyzer has detected an arithmetic expression where a signed integer overflow may occur\.

The example:

```cpp
long long foo()
{
  long longOperand = 0x7FFF'FFFF;
  long long y = longOperand * 0xFFFF;
  return y;
}
```

According to the C and C\+\+ rules, the result type of the `longOperand * 0xFFFF` expression will be `long`\. On Windows, when using the MSVC compiler, the `long` type is [4 bytes](https://pvs-studio.com/en/blog/terms/0012/) in size\. The maximum value that can be represented by this type is 2'147'483'647 in decimal or 0x7FFF'FFFF in hexadecimal\. When multiplying the `longOperand` variable by 0xFFFF \(65,535\), the 0x7FFF'7FFF'0001 result is expected\. However, as specified in the C18 standard \([section 6\.5](https://web.archive.org/web/20181230041359if_/http:/www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf#page=74), paragraph 5\) and C\+\+20 \([section 7\.1](https://timsong-cpp.github.io/cppwp/n4861/expr#pre-4), paragraph 4\), the [signed integer overflow](https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow) leads to undefined behavior\.

There are several ways to fix this code\.

To evaluate expressions correctly, use types with a size large enough to hold the expected value\. If the value does not fit a machine word, use one of the libraries for arbitrary\-precision arithmetic, such as [GMP](https://gmplib.org/), [MPRF](https://www.mpfr.org/), and [cnl](https://github.com/johnmcfarlane/cnl)\.

The code fragment above can be fixed as follows:

```cpp
long long foo()
{
  long longOperand = 0x7FFF'FFFF;
  long long y = static_cast<long long>(longOperand) * 0xFFFF;
  return y;
}
```

To handle the signed integer overflow as an unintended behavior, use specialized libraries that provide safe integer operations, such as [boost::safe\_numerics](https://github.com/boostorg/safe_numerics) or [Google Integers](https://github.com/google/integers)\.

To implement wraparound arithmetic for signed integers with standard\-defined behavior, use unsigned integers for evaluations\. When the unsigned integer overflow occurs, the integer wraps around modulo `2 ^ n`, where `n` is the number of bits within the integer\.

The possible solution based on `[std::bit_cast](https://en.cppreference.com/w/cpp/numeric/bit_cast)` \(C\+\+20\):

```cpp
#include <concepts>
#include <type_traits>
#include <bit>
#include <functional>

namespace detail
{
  template <std::signed_integral R,
            std::signed_integral T1,
            std::signed_integral T2,
            std::invocable<std::make_unsigned_t<T1>,
                           std::make_unsigned_t<T2>> Fn>
  R safe_signed_wrapper(T1 lhs, T2 rhs, Fn &&op)
    noexcept(std::is_nothrow_invocable_v<Fn,
                                         std::make_unsigned_t<T1>,
                                         std::make_unsigned_t<T2>>)
  {
    auto uLhs = std::bit_cast<std::make_unsigned_t<T1>>(lhs);
    auto uRhs = std::bit_cast<std::make_unsigned_t<T2>>(rhs);

    auto res = std::invoke(std::forward<Fn>(op), uLhs, uRhs);

    using UR = std::make_unsigned_t<R>;
    return std::bit_cast<R>(static_cast<UR>(res));
  }
}
```

The `std::bit_cast` function converts `lhs` and `rhs` to the corresponding unsigned representations\. Next, some arithmetic operation is performed on the two converted operands\. After that, the result is expanded or narrowed to the required result type and converted to a signed one\.

With this approach, signed integers follow the semantics of unsigned ones in arithmetic operations\. This does not lead to undefined behavior\. 

For example, you can see [here](https://godbolt.org/z/vqP5bjYWz) that the compiler may optimize the code if it detects the signed integer overflow\.

The example:

```cpp
bool is_max_int(int32_t a)
{
  return a + 1 < a;
}
```

If `a` equals `MAX_INT`, the `a + 1 < a` condition will be `false`\. This is a way to check whether an overflow has occurred\. However, the compiler generates the following code:

```cpp
is_max_int(int):                        # @is_max_int(int)
        xor     eax, eax
        ret
```

The assembly `xor eax, eax` instruction resets the result of the `is_max_int` function execution\. As a result, the latter function always returns `true`, no matter what the `a` value has\. In this case, this is the result of undefined behavior due to overflow\.

In the case of an unsigned representation, undefined behavior does not occur:

```cpp
is_max_int(int):                        # @is_max_int(int)
        cmp     edi, 2147483647
        sete    al
        ret
```

The compiler has generated code that does check the condition\.

**Note**\. The diagnostic rule supports a special setting that enables the analyzer to detect overflow in both signed and unsigned numeric types\.

To enable this setting, add the following comment to the source code or to the diagnostic rules configuration file \(`[.pvsconfig](https://pvs-studio.com/en/docs/manual/6630/?ysclid=mauu5h7en219076378)`\):

`//+V1083 CHECK_UNSIGNED_OVERFLOW:YES`

To disable the setting, add the comment:

`//+V1083 CHECK_UNSIGNED_OVERFLOW:NO`

## Additional diagnostic rule settings

The diagnostic rule supports additional settings\. To enable them, [add](https://pvs-studio.com/en/docs/manual/0040/) the comment to the source code file or to the diagnostic rule configuration file, `[.pvsconfig](https://pvs-studio.com/en/docs/manual/6630/?ysclid=mauu5h7en219076378)`\.

### Detecting unsigned integer overflow

The setting allows the analyzer to additionally detect overflow of unsigned integer types\. To enable the setting, add the comment:

```cpp
//+V1083 CHECK_UNSIGNED_OVERFLOW:YES
```

To disable it, use the comment:

```cpp
//+V1083 CHECK_UNSIGNED_OVERFLOW:NO
```

### Pedantic mode

The setting allows the analyzer to detect integer type overflow in cases where the analyzer does not have a data of the value of at least one of the operands\. To enable the setting, add one of the following comments:

```cpp
//+V1083 PEDANTIC_MODE
//+V1083 PEDANTIC_MODE:YES
```

To disable it, use the comment:

```cpp
//+V1083 PEDANTIC_MODE:NO
```