parts/6.15.ArithmeticWrap-aroundError-FIF.md

6.15 Arithmetic Wrap-around Error [FIF]

6.15.1 Applicability to language

C++ has the vulnerability as documented in ISO/IEC 24772-1 clause 6.15, since overflow situations are undefined behaviour for signed integer arithemtic and wrap-around for unsigned integer arithmetic, which can lead to surprising results. C++ specifies that

For example, integral promotion happens when multiplying two unsigned short operands which can result in undefined behavior:

auto f(){
  std::uint16_t x{50'000},y{50'000};
  return x * y; // undefined behaviour due to overflow, returns int
}

In the above, for a 16-bit short and a 32-bit int, i.e., std::numeric_limits<int>::max()==0x7fff'ffff, x and y are promoted to int and the multiplication then overflows which is undefined behaviour.

Even when operands have the same unsigned type, wrap-around arithmetic can be confusing, for example, 4U - 5U yields a large positive value.

Calling a function taking a parameter of integral type with an argument of different integral type works due to implicit conversions. If a different overload with a better match becomes visible the called function can change when re-compiled (see 6.21 Namespace Issues[BJL])

Using brace-initialization prevents implicit narrowing conversions in contrast to other forms of initialization. For example:

std::uint16_t x{500'000};  // won't compile due to narrowing
std::uint16_t y = 500'000; // compiles, but truncates value

The mitigations for wrap-around errors in C++ are different than for C. The type system of C++ allows user-defined class and enum types with corresponding overloaded operators. Such user-defined types can individually control which implicit conversions or mixed type arithmetic they support, if any. For example, one can force arithmetic to be done with unsigned types:

enum class uint16: std::uint16_t{};
uint16 operator*(uint16 a, uint16 b){
  return static_cast<uint16>(static_cast<unsigned>(a) * static_cast<unsigned>(b));
} // guarantee wrap-around

High-integrity software using the built-in integral types should

6.15.2 Avoidance mechanisms for language users

To avoid the vulnerability or mitigate its ill effects, C++ software developers can: