re PR middle-end/64242 (Longjmp expansion incorrect)
authorWilco Dijkstra <wdijkstr@arm.com>
Fri, 30 Nov 2018 23:06:51 +0000 (23:06 +0000)
committerJeff Law <law@gcc.gnu.org>
Fri, 30 Nov 2018 23:06:51 +0000 (16:06 -0700)
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
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr64242.c [new file with mode: 0644]

index bda587bbfffc26e06f5845d5421bf8fe2dc27f6d..6c57ed0027ee1b2f8d7f5e85f1f11b9c217f3dc0 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-30  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       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  <dmalcolm@redhat.com>
 
        * diagnostic-core.h (emit_diagnostic): New decl.
index 537228cf3bed0c58b5f21ae43eeb82c1adea6f16..669e548706f537fa9a92c5f47f30fc3c6ee38176 100644 (file)
@@ -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.  */
index c5b551319ac158f1e1d8811ac2daee634e568959..903f7cb34047233981420044ca65e53cfaeb9a66 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-30  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       PR middle-end/64242
+       * gcc.c-torture/execute/pr64242.c: New test.
+
 2018-11-30  David Malcolm  <dmalcolm@redhat.com>
 
        * 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 (file)
index 0000000..72dab57
--- /dev/null
@@ -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;
+}