Checking for Integer Overflow

Dave Sinkula 0 Tallied Votes 351 Views Share

To check for integer overflow, you can't simply check the outcome of an operation, you need to check before the operation. So how do you do that? This example checks for overflow with multiplication.

#include<stdio.h>
#include<limits.h>

int foo(int a, int b, int *result)
{
   if ( a > 0 && b > 0 )
   {
      /*
       * 'a' is positive, 'b' is positive, product will be positive.
       * See if one positive value 'b' is more than the most positive int
       * divided by the other positive value 'a' (positive quotient).
       */
      if ( b > INT_MAX / a )
      {
         return -1;
      }
   }
   else if ( a > 0 && b < 0 )
   {
      /*
       * 'a' is positive, 'b' is negative, product will be negative.
       * See if the negative value 'b' is less than the most negative int
       * divided by the positive value 'a' (negative quotient).
       */
      if ( b < INT_MIN / a )
      {
         return -1;
      }
   }
   else if ( a < 0 && b > 0 )
   {
      /*
       * 'a' is positive, 'b' is negative, product will be negative.
       * See if the negative value 'a' is less than the most negative int
       * divided by the positive value 'b' (negative quotient).
       */
      if ( a < INT_MIN / b )
      {
         return -1;
      }
   }
   else /* if (a < 0 && b < 0) */
   {
      /*
       * 'a' is negative, 'b' is negative, product will be positive.
       * See if one negative value 'b' is less than the most positive int
       * divided by the other negative value 'a' (negative quotient).
       */
      if ( b < INT_MAX / a )
      {
         return -1;
      }
   }
   *result = a * b;
   return 0;
}

void bar(int a, int b)
{
   int product;
   printf("a = %d, b = %d, ", a, b);
   if ( foo(a, b, &product) < 0 )
   {
      puts("overflow warning");
   }
   else
   {
      printf("a * b = %d\n", a * b);
   }
}

int main(void)
{
   int a, b;
   printf("INT_MAX = %d\n", INT_MAX);
   printf("INT_MIN = %d\n", INT_MIN);
   for ( a =  10, b =  5; a < INT_MAX / 10; a *= 10, b *= 10 )
   {
      bar(a,b);
   }
   for ( a =  10, b = -5; a < INT_MAX / 10; a *= 10, b *= 10 )
   {
      bar(a,b);
   }
   for ( a = -10, b =  5; a > INT_MIN / 10; a *= 10, b *= 10 )
   {
      bar(a,b);
   }
   for ( a = -10, b = -5; a > INT_MIN / 10; a *= 10, b *= 10 )
   {
      bar(a,b);
   }
   return 0;
}

/* my output
INT_MAX = 2147483647
INT_MIN = -2147483648
a = 10, b = 5, a * b = 50
a = 100, b = 50, a * b = 5000
a = 1000, b = 500, a * b = 500000
a = 10000, b = 5000, a * b = 50000000
a = 100000, b = 50000, overflow warning
a = 1000000, b = 500000, overflow warning
a = 10000000, b = 5000000, overflow warning
a = 100000000, b = 50000000, overflow warning
a = 10, b = -5, a * b = -50
a = 100, b = -50, a * b = -5000
a = 1000, b = -500, a * b = -500000
a = 10000, b = -5000, a * b = -50000000
a = 100000, b = -50000, overflow warning
a = 1000000, b = -500000, overflow warning
a = 10000000, b = -5000000, overflow warning
a = 100000000, b = -50000000, overflow warning
a = -10, b = 5, a * b = -50
a = -100, b = 50, a * b = -5000
a = -1000, b = 500, a * b = -500000
a = -10000, b = 5000, a * b = -50000000
a = -100000, b = 50000, overflow warning
a = -1000000, b = 500000, overflow warning
a = -10000000, b = 5000000, overflow warning
a = -100000000, b = 50000000, overflow warning
a = -10, b = -5, a * b = 50
a = -100, b = -50, a * b = 5000
a = -1000, b = -500, a * b = 500000
a = -10000, b = -5000, a * b = 50000000
a = -100000, b = -50000, overflow warning
a = -1000000, b = -500000, overflow warning
a = -10000000, b = -5000000, overflow warning
a = -100000000, b = -50000000, overflow warning
*/