Fix PR64242 - the middle end expansion for long jmp updates the hard frame pointer before it reads the new stack pointer. This results in a corrupted stack pointer if the jmp buffer is a local. The obvious fix is to insert a temporary.
AArch64 bootstrap & regress pass. OK to commit? ChangeLog: 2018-11-29 Wilco Dijkstra <wdijk...@arm.com> gcc/ PR middle-end/64242 * builtins.c (expand_builtin_longjmp): Use a temporary when restoring the frame pointer. (expand_builtin_nonlocal_goto): Likewise. testsuite/ PR middle-end/64242 * gcc.c-torture/execute/pr64242.c: New test. --- diff --git a/gcc/builtins.c b/gcc/builtins.c index ebde2db6e6494cf7e4441f6834e65fcb81e1629c..5c80c60378fc4fbb3faf8e04672d7091ac071624 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1142,8 +1142,11 @@ expand_builtin_longjmp (rtx buf_addr, rtx value) emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - emit_move_insn (hard_frame_pointer_rtx, fp); + /* Restore the frame pointer and stack pointer. We must use a + temporary since the setjmp buffer may be a local. */ + fp = copy_to_reg (fp); emit_stack_restore (SAVE_NONLOCAL, stack); + emit_move_insn (hard_frame_pointer_rtx, fp); emit_use (hard_frame_pointer_rtx); emit_use (stack_pointer_rtx); @@ -1286,9 +1289,11 @@ expand_builtin_nonlocal_goto (tree exp) emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - /* Restore frame pointer for containing function. */ - emit_move_insn (hard_frame_pointer_rtx, r_fp); + /* Restore the frame pointer and stack pointer. We must use a + temporary since the setjmp buffer may be a local. */ + r_fp = copy_to_reg (r_fp); emit_stack_restore (SAVE_NONLOCAL, r_sp); + emit_move_insn (hard_frame_pointer_rtx, r_fp); /* USE of hard_frame_pointer_rtx added for consistency; not clear if really needed. */ diff --git a/gcc/testsuite/gcc.c-torture/execute/pr64242.c b/gcc/testsuite/gcc.c-torture/execute/pr64242.c new file mode 100644 index 0000000000000000000000000000000000000000..72dab5709203437b50514a70c523d104706e4bda --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr64242.c @@ -0,0 +1,30 @@ +/* { dg-require-effective-target indirect_jumps } */ + +extern void abort (void); + +__attribute ((noinline)) void +broken_longjmp(void *p) +{ + void *buf[5]; + __builtin_memcpy (buf, p, 5 * sizeof (void*)); + /* Corrupts stack pointer... */ + __builtin_longjmp (buf, 1); +} + +volatile int x = 0; +volatile void *p; +int +main (void) +{ + void *buf[5]; + p = __builtin_alloca (x); + + if (!__builtin_setjmp (buf)) + broken_longjmp (buf); + + /* Fails if stack pointer corrupted. */ + if (p != __builtin_alloca (x)) + abort(); + + return 0; +}