How to detect integer overflow in C

18,407

Solution 1

You can predict signed int overflow but attempting to detect it after the summation is too late. You have to test for possible overflow before you do a signed addition.

It's not possible to avoid undefined behaviour by testing for it after the summation. If the addition overflows then there is already undefined behaviour.

If it were me, I'd do something like this:

#include <limits.h>

int safe_add(int a, int b) 
{
    if (a >= 0) {
        if (b > (INT_MAX - a)) {
            /* handle overflow */
        }
    } else {
        if (b < (INT_MIN - a)) {
            /* handle underflow */
        }
    }
    return a + b;
}

Refer this paper for more information. You can also find why unsigned integer overflow is not undefined behaviour and what could be portability issues in the same paper.

EDIT:

GCC and other compilers have some provisions to detect the overflow. For example, GCC has following built-in functions allow performing simple arithmetic operations together with checking whether the operations overflowed.

bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
bool __builtin_sadd_overflow (int a, int b, int *res)
bool __builtin_saddl_overflow (long int a, long int b, long int *res)
bool __builtin_saddll_overflow (long long int a, long long int b, long long int *res)
bool __builtin_uadd_overflow (unsigned int a, unsigned int b, unsigned int *res)
bool __builtin_uaddl_overflow (unsigned long int a, unsigned long int b, unsigned long int *res)
bool __builtin_uaddll_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *res)

Visit this link.

EDIT:

Regarding the question asked by someone

I think, it would be nice and informative to explain why signed int overflow undefined, whereas unsigned apperantly isn't..

The answer depends upon the implementation of the compiler. Most C implementations (compilers) just used whatever overflow behaviour was easiest to implement with the integer representation it used.

In practice, the representations for signed values may differ (according to the implementation): one's complement, two's complement, sign-magnitude. For an unsigned type there is no reason for the standard to allow variation because there is only one obvious binary representation (the standard only allows binary representation).

Solution 2

You cannot detect signed int overflow. You have to write your code to avoid it.

Signed int overflow is Undefined Behaviour and if it is present in your program, the program is invalid and the compiler is not required to generate any specific behaviour.

Solution 3

Signed operands must be tested before the addition is performed. Here is a safe addition function with 2 comparisons in all cases:

#include <limits.h>

int safe_add(int a, int b) {
    if (a >= 0) {
        if (b > INT_MAX - a) {
            /* handle overflow */
        } else {
            return a + b;
        }
    } else {
        if (b < INT_MIN - a) {
            /* handle negative overflow */
        } else {
            return a + b;
        }
    }
}

If the type long long is known to have a larger range than type int, you could use this approach, which might prove faster:

#include <limits.h>

int safe_add(int a, int b) {
    long long res = (long long)a + b;
    if (res > INT_MAX || res < INT_MIN) {
        /* handle overflow */
    } else {
        return (int)res;
    }
}
Share:
18,407

Related videos on Youtube

Dean
Author by

Dean

Updated on July 26, 2022

Comments

  • Dean
    Dean almost 2 years

    We know CPython promotes integers to long integers (which allow arbitrary-precision arithmetic) silently when the number gets bigger.

    How can we detect overflow of int and long long in pure C?

    • Some programmer dude
      Some programmer dude about 5 years
      It's very tricky since you just can't add two numbers and check if the value is above some threshold (because signed integer arithmetic overflow and such). A simple solution might be to check if x (the value you want to check) is above a specific threshold, or if adding one goes above a threshold. If it does and the other number you want to add is larger than one, then you have an overflow situation.
    • Antti Haapala -- Слава Україні
      Antti Haapala -- Слава Україні about 5 years
      Nitpick, but, it was CPython 2.7 that did this. CPython 3 doesn't "promote" anything, even internally there is just one type.
    • phuclv
      phuclv about 5 years
      there are a lot of duplicates depending on what you want to do with the values (add/sub/mul/div/...?) How to check if A+B exceed long long? (both A and B is long long), Detecting signed overflow in C/C++, Test for overflow in integer addition
    • NoChance
      NoChance about 5 years
  • A.R.C.
    A.R.C. about 5 years
    You can check you input values before doing a calculation to prevent overflow.
  • hetepeperfan
    hetepeperfan about 5 years
    I think, it would be nice and informative to explain why signed int overflow undefined, whereas unsigned apperantly isn't..
  • chqrlie
    chqrlie about 5 years
    Why extra parentheses? Also you could save one test on average with if (a >= 0) { test overflow } else { test underflow } return a + b;
  • Antti Haapala -- Слава Україні
    Antti Haapala -- Слава Україні about 5 years
    @chqrlie that is not sufficient because there is no possibility of overflow when a == 0.
  • chqrlie
    chqrlie about 5 years
    It is not necessary to test overflow if a == 0 but testing a just once saves one comparison if a < 0, which is half the cases.
  • Antti Haapala -- Слава Україні
    Antti Haapala -- Слава Україні about 5 years
    Also, both are technically called overflow. Underflow means that the value is too small in magnitude to be representable in a floating point variable.
  • Antti Haapala -- Слава Україні
    Antti Haapala -- Слава Україні about 5 years
    @chqrlie but your change was incorrect because it ignores the test a == 0 which was implicit there, i.e. nothing was saved.
  • chqrlie
    chqrlie about 5 years
    Here is what I mean: if (a >= 0) { if (b > INT_MAX - a) { /* handle overflow */ }} else { if (b < INT_MIN - a) { /* handle overflow */ }} return a + b;. 2 comparisons in all cases as opposed to 2.5 for the current answer code.
  • chqrlie
    chqrlie about 5 years
    @AnttiHaapala it does not ignore the case a == 0 where there is no possible overflow, it just handles it differently.
  • Sneftel
    Sneftel about 5 years
    @hetepeperfan It's because that's what the language standard says.
  • hetepeperfan
    hetepeperfan about 5 years
    @sneftel thats an authoritative argument lacking an authoritative source, despise it is probably correct. On top of that, standards make more sense to people, once they start to understand the language, which is perhaps a reason they visit stackoverflow in the first place.
  • Holger
    Holger about 5 years
    @hetepeperfan there surely is already a Q&A on Stackoverflow regarding the reason behind this choice. So there’s no reason to discuss it here, where the OP never asked about it.
  • Antti Haapala -- Слава Україні
    Antti Haapala -- Слава Україні about 5 years
    @hetepeperfan the reason for why the standard is written as it is, is for the most part outside the scope of Stack Overflow.
  • Jesper Juhl
    Jesper Juhl about 5 years
    @hetepeperfan Making it well defined has a cost on some implementations and leaving it undefined enables various compiler optimizations.
  • chqrlie
    chqrlie about 5 years
    @abhiarora: you did not copy my coding suggestion proposal correctly. I took the liberty to correct the tests.
  • hetepeperfan
    hetepeperfan about 5 years
    @JesperJuhl This I understand, when your out of bits, your out. Probably C only gets more complicated when int32_t get promoted to int64_t, depending on whether the operation overflows or not. I just felt, that pointing to standards doesn't make the answer clear to a large audience. even when reading C11 N1570 6.5.3 semantic 2 says "The result of the binary*operator is the product of the operands", I've been looking, but unable to tell where in standard I can find that a overflow is undefined, although I do reasonably understand.
  • hamilyon
    hamilyon almost 3 years
    I carefully read documentation and I see nothing that guarantees that INT_MIN - a or INT_MAX - a itself cannot overflow. The fact that on all current architectures it seems to be true means nothing regarding to standard.
  • Eyal
    Eyal over 2 years
    What if you cast the signed ints to unsigned ints? Though the overflow result is undefined, overflow of unsigned ints is defined. So to test if a+b is overflow, test if (uint)a + (uint)b < (uint)a. Casting the int to uint is well-defined and so is all the rest. The compiler will probably be able to cast the numbers with 0 instructions.
  • Eyal
    Eyal over 2 years
    @hamilyon Notice that INT_MIN - a is only run if a is less than 0, which means that the result will be INT_MIN plus number number that is, at most, INT_MAX. So the result will be between INT_MIN and 0, so no overflow.