Home > Enterprise >  Does this function address arithmetic overflow/underflow?
Does this function address arithmetic overflow/underflow?

Time:05-10

I am trying to create a function in C language that reads a string of command line integers and takes the sum of all the numbers without causing arithmetic overflow/underflow. I understand most of overflow/underflow concepts, but am struggling to apply it to my function.

Here is the code that I have created thus far:

int main(int argc, char * argv[]) {
  int sum = 0, i;
  if (argc <= 1) {

    printf(" Enter integers into command line after command to run .exe file ");
    exit(0);

  } else {
    for (i = 1; i < argc; i  ) {
      sum  = atoi(argv[i]);
    }
  }

  printf(" Sum of all command line arguments is %d ", sum);

}

I am curious to see if this addresses arithmetic overflow/underflow or if it is still missing something.

CodePudding user response:

if this addresses arithmetic overflow/underflow or if it is still missing something.

OP's code has no certain overflow protection. atoi() on overflow is undefined behavior (UB). On overflow, it might return a large int, might "wrap", might do terrible things - it is UB.


Instead of atoi(), use strtol() to detect string to integer overflow. Look at errno after calling strtol().

  errno = 0;
  long val = strtol(argv[i], 0, 10);
  if (errno) {
    Handle_Overflow();
  }

Rather than just add, look for potential overflow before doing the addition as overflow of signed integer overflow is more UB.

long sum = 0;
...
  if ((val < 0) ? (sum < LONG_MIN - val) : (sum > LONG_MAX - val)) {
    Handle_Overflow();
  } else {
    sum  = val;
  }

Could use widest integer type intmax_t for maximal usable range without resorting to multi-objects.

A sum less than the a signed integer's range is sometimes called underflow. More commonly that is simply called overflow too.


  intmax_t sum = 0;
  for (i = 1; i < argc; i  ) {
    char *endptr;
    errno = 0;
    intmax_t val = strtoimax(argv[i], &endptr, 10);
    if (endptr == argv[i] || *endptr) {
      Handle_non_numeric_input();
    }
    if (errno == ERANGE) {
      Handle_overflow();
    }

    if ((val < 0) ? (sum < INTMAX_MIN - val) : (sum > INTMAX_MAX - val)) {
      Handle_Overflow();
    }
    sum  = val;
  }

  printf(" Sum of all command line arguments is %jd\n", sum);

CodePudding user response:

If you pass two arguments, both of which are INT_MAX/2 10 (1,073,741,834 on 32-bit platform), then the sum should properly be INT_MAX 20, which clearly overflows an int.

I see nothing that would "address" that overflow.


This is how I would address it:
for (i = 1; i < argc; i  ) {
    // if sum argv[i] > INT_MAX, then show an error message.
    if (INT_MAX - sum > atoi(argv[i]))
    {
        printf("The next sum will overflow!\n");
        exit();
    }
    sum  = atoi(argv[i]);
}

A more complete and correct implementation would have to consider if sum and argv[i] are positive or negative values. But I think this illustrates the basic idea for starters.

  •  Tags:  
  • c
  • Related