https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97264
Bug ID: 97264 Summary: [11 Regression] -fpa-modref breaks va_arg on glibc Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: ipa Assignee: unassigned at gcc dot gnu.org Reporter: slyfox at gcc dot gnu.org CC: hubicka at gcc dot gnu.org, marxin at gcc dot gnu.org Target Milestone: --- Initially spotted the problem on glibc form master where fscanf() breaks in complex ways. I tried to minimize fscanf() down to a single file. Looks like -fno-ipa-modref changes crashing to non-crashing program. Full example: // extracted from glibc's __vfscanf_internal() void __isoc99_fscanf__ (const char *format, ...) __attribute__((noipa)); void __vfscanf_internal__ (const char *format, __builtin_va_list argptr) __attribute__((noipa)); #define isd(c) ({ int __c = (c); __c >= '0' && __c <= '9'; }) static int read_int (const unsigned char **pstr) { // read first digit '1' int retval = **pstr - '0'; // skip digits: executes 0 times and advances pointer once while (isd (*++(*pstr))) ; return retval; } void __vfscanf_internal__ (const char *f, __builtin_va_list argptr) { /* assume input: "1<>\0" */ while (*f != '\0') { const unsigned char ** pstr = (const unsigned char **) &f; // skip digit '1' read_int (pstr); /* Find the conversion specifier. */ f++; // skip '<' char * str = __builtin_va_arg(argptr, char *); f++; // skip ">" *str++ = '?'; } } void __isoc99_fscanf__ (const char *format, ...) { __builtin_va_list arg; __builtin_va_start (arg, format); __vfscanf_internal__ (format, arg); __builtin_va_end (arg); } int main (void) { char key[10]; __isoc99_fscanf__ ("1<>", key); return 0; } How to crash: $ gcc-11.0.0 -O2 uname.c -o uname11 && ./uname11 Segmentation fault (core dumped) $ gcc-11.0.0 -O2 uname.c -o uname11 -fno-ipa-modref && ./uname11 <ok>