From 71b144289c1c69a6d8eec9fd1dc64aecaf3ebed6 Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Fri, 30 Nov 2018 23:06:51 +0000 Subject: [PATCH] re PR middle-end/64242 (Longjmp expansion incorrect) PR middle-end/64242 * builtins.c (expand_builtin_longjmp): Use a temporary when restoring the frame pointer. (expand_builtin_nonlocal_goto): Likewise. * gcc.c-torture/execute/pr64242.c: New test. From-SVN: r266697 --- gcc/ChangeLog | 7 +++++ gcc/builtins.c | 11 +++++-- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.c-torture/execute/pr64242.c | 30 +++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr64242.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bda587bbfff..6c57ed0027e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-11-30 Wilco Dijkstra + + PR middle-end/64242 + * builtins.c (expand_builtin_longjmp): Use a temporary when restoring + the frame pointer. + (expand_builtin_nonlocal_goto): Likewise. + 2018-11-30 David Malcolm * diagnostic-core.h (emit_diagnostic): New decl. diff --git a/gcc/builtins.c b/gcc/builtins.c index 537228cf3be..669e548706f 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1143,8 +1143,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); @@ -1287,9 +1290,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/ChangeLog b/gcc/testsuite/ChangeLog index c5b551319ac..903f7cb3404 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-11-30 Wilco Dijkstra + + PR middle-end/64242 + * gcc.c-torture/execute/pr64242.c: New test. + 2018-11-30 David Malcolm * g++.dg/parse/missing-parens-fixit.C: New test. 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 00000000000..72dab570920 --- /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; +} -- 2.30.2