https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91989
Bug ID: 91989 Summary: libssp/spp.c: __[stack_]chk_fail() may run arbitrary code if __builtin_trap() returns Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: franke at computer dot org Target Milestone: --- Issue found in MinGW-w64 GCC 7.4.0 from current Cygwin package, but still applies to current SVN trunk (r276567): The abort code used by __[stack_]chk_fail() assumes that something may prevent __builtin_trap() (and segfault) from working: libssp/ssp.c: static void fail (......) { ... /* Try very hard to exit. Note that signals may be blocked preventing the first two options from working. The use of volatile is here to prevent optimizers from "knowing" that __builtin_trap is called first, and that it doesn't return, and so "obviously" the rest of the code is dead. */ { volatile int state; for (state = 0; ; state++) switch (state) { case 0: __builtin_trap (); break; case 1: *(volatile int *)-1L = 0; break; case 2: _exit (127); break; } } } The volatile state variable only prevents that the loop is optimized away, but does not prevent that the compiler assumes an __attribute__((noreturn)) for __builtin_trap(): gcc/builtins.c: void expand_builtin_trap (void) { ... emit_barrier (); } Depending on how the optimizer moves code around, this may result in arbitrary code following __builtin_trap(). In libssp.a from Mingw-w64 GCC 7.0.3, the generated code is equivalent to: volatile int state; for (state = 0; ; state++) switch (state) { case 0: __builtin_trap (); // fall through ... case 2: _exit (127); break; case 1: *(volatile int *)-1L = 0; break; } In this case, we were lucky. But if gcc would decide to move 'case 0:' code to the end of the function, arbitrary code from start of next function would be executed. Conclusion: If there are runtime settings that let __buildin_trap() return, the compiler should not assume an __attribute__((noreturn)) for this builtin. If there are no such settings, the volatile loop in ssp.c is not needed.