-1

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.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 9
    Which part here is supposed to address it? – Eugene Sh. May 09 '22 at 18:51
  • Since `atoi()` has no protection against overflow, it is hard to see how your code is protected at all. Try running it with a few 15-digit integers as arguments — and the odd word or two (like `abc` and `xyz`) — and see whether it behaves sanely. Use `strtol()` to convert argument strings to numbers (the return value is a `long`, of course — see [Correct usage of `strtol()`?](https://stackoverflow.com/questions/14176123/correct-usage-of-strtol/14176593#14176593)). Then you have to do overflow protection on the arithmetic (`sum += atoi(argv[i]);` does nothing to protect against overflow). – Jonathan Leffler May 09 '22 at 18:59
  • It isn't clear what you mean by "addressing arithmetic overflow". What is supposed to happen? Should the function output the right answer even if some of the numbers are too large to fit in an `int`? Should it detect that there was an overflow and complain? Should it minimize the chances of an overflow by doing something more clever than straight addition, and then complain if it was unsuccessful? By the way there is no such thing as integer underflow. – n. m. could be an AI May 09 '22 at 19:36
  • @n.1.8e9-where's-my-sharem. *By the way there is no such thing...* That might be my fault. Perhaps he was misled by my mention of it in [this answer](https://stackoverflow.com/questions/72114418/assigning-a-char-pointer-to-string-literal-generated-at-runtime-is-this-dynami/72115008#72115008). :-) – Steve Summit May 09 '22 at 19:56
  • @SteveSummit You forgot to mention EANSWERLATEBY34DAYS. – n. m. could be an AI May 09 '22 at 20:05

2 Answers2

1

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. strtol() has well defined functionality on 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;
...
  // Will adding result in a sum outside the `long` range?
  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 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);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

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.

abelenky
  • 63,815
  • 23
  • 109
  • 159