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

            Bug ID: 120704
           Summary: [14/15/16 regression] Wrong O3 optimization leads to
                    UBs and SIGSEGV
           Product: gcc
           Version: 14.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: congli at smail dot nju.edu.cn
  Target Milestone: ---

Compiler explorer: https://godbolt.org/z/o9d5bT4z7

After compiling the following case with -O3, a segfault is encountered when
executing the binary. -O{0,1,2,s} works well. This is a bug ever since GCC 14.

When further adding `-fsanitize=undefined`, some UBs appear with -O3, but not
-O{0,1,2,s}. Also no UBs using clang and compcert.

Note, flags `-fno-tree-slsr -fno-ivopts -fno-jump-tables` doesn't work on this
case.


```
$ cat a.c
long a, b;
int c, d, e, g;
int *j(int *k, int l) { 
  // l is always -2147634
  return l ? k + l + 2147634 : k; 
}
static int n(int k) {
  goto ao;
ap:
  e = -14 * e - 7 * c - 2147483647;
  if (-999 * ((b && a) + e) + g - 2147483647 >= 0)
    goto aq;
  k = 1;
  if (e)
    goto ar;
as:
  e = -999 * g - 2147483647;
  if (-e + k - 1000 * g - 1997280 >= 0)
    goto ap;
  goto aq;
ao:
  c = -999 - 2148634;
at:
  g = -999 * g - 1278003;
  if (-779 * g + 999 * c + 1150259692 >= 0)
    goto aq;
  goto au;
aq:
  c = -999 * g - 2429352;
  goto at;
au:
  g = -999 * c - 2147483647;
  goto as;
ar:
  d = *j(&c, c);
  return a;
}
int main() {
  while (!(n(-2145487648) - 1))
    ;
  return 0;
}


$ gcc -O3 a.c && ./a.out
[1]    17774 segmentation fault  ./a.out

$ gcc -O3 -fsanitize=undefined a.c && ./a.out
/tmp/a.c:10:11: runtime error: signed integer overflow: -2147203927 * -14
cannot be represented in type 'int'
/tmp/a.c:10:11: runtime error: signed integer overflow: -2146205926 * -14
cannot be represented in type 'int'
/tmp/a.c:10:23: runtime error: signed integer overflow: -2840684 - 2147483647
cannot be represented in type 'int'
```

The tricky thing might be the `j()` function. However at runtime, the value of
`l` in `j()` is always -2147634, so `j()` is always returning k which is well
defined.

Reply via email to