[Bug c/87311] New: missing integer overflow detection on negation of the minimum value with -ftrapv or UB sanitizer

vincent-gcc at vinc17 dot net gcc-bugzilla@gcc.gnu.org
Fri Sep 14 20:01:00 GMT 2018


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87311

            Bug ID: 87311
           Summary: missing integer overflow detection on negation of the
                    minimum value with -ftrapv or UB sanitizer
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vincent-gcc at vinc17 dot net
  Target Milestone: ---

When using -ftrapv or -fsanitize=undefined, GCC sometimes misses integer
overflow detection on negation of the minimum value (e.g. LONG_MIN for type
long). For instance:

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

int main (void)
{
  long i, j;

  i = j = LONG_MIN;
  i = -i - 1;
  fprintf (stderr, "%ld\n", i);
  j = -j;
  fprintf (stderr, "%ld\n", j);
  return 0;
}

$ gcc-snapshot tst.c -o tst -ftrapv
$ ./tst
9223372036854775807
zsh: abort (core dumped)  ./tst

Integer overflow on -j is detected, but not the one on -i. With optimizations,
none is detected:

$ gcc-snapshot tst.c -o tst -ftrapv -O
$ ./tst
9223372036854775807
-9223372036854775808

which is particularly bad because the code may assume that negating a negative
value yields a positive value.

With -fsanitize=undefined, one gets the expected error "runtime error: negation
of -9223372036854775808 cannot be represented in type 'long int'; cast to an
unsigned type to negate this value to itself" only for -j (with or without
optimizations).

All GCC versions seem to be affected, including the trunk.


More information about the Gcc-bugs mailing list