Hi!

As discussed in the PR and suggested by Uros, scheduler has code to keep a
use of hard register next to the assignment that sets that hard register
from a pseudo, which is desirable so that RA can deal with it properly.
Unfortunately, with -fstack-protector* we stick the stack protect epilogue
in between, which splits the load and use to different basic blocks.
The code emitted by expand_function_end between these two spots is only the
loading of the return value into registers, so generally it shouldn't
contain any stores which stack protection wants to guard against, so I
believe from security POV this shouldn't weaken anything, but fixes the
testcase.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-02-01  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/87485
        * function.c (expand_function_end): Move stack_protect_epilogue
        before loading of return value into hard register(s).

        * gcc.dg/pr87485.c: New test.

--- gcc/function.c.jj   2019-01-29 16:47:02.000000000 +0100
+++ gcc/function.c      2019-02-01 16:23:07.471877843 +0100
@@ -5330,6 +5330,10 @@ expand_function_end (void)
      communicate between __builtin_eh_return and the epilogue.  */
   expand_eh_return ();
 
+  /* If stack protection is enabled for this function, check the guard.  */
+  if (crtl->stack_protect_guard && targetm.stack_protect_runtime_enabled_p ())
+    stack_protect_epilogue ();
+
   /* If scalar return value was computed in a pseudo-reg, or was a named
      return value that got dumped to the stack, copy that to the hard
      return register.  */
@@ -5475,10 +5479,6 @@ expand_function_end (void)
       && targetm_common.except_unwind_info (&global_options) != UI_SJLJ)
     emit_insn (gen_blockage ());
 
-  /* If stack protection is enabled for this function, check the guard.  */
-  if (crtl->stack_protect_guard && targetm.stack_protect_runtime_enabled_p ())
-    stack_protect_epilogue ();
-
   /* If we had calls to alloca, and this machine needs
      an accurate stack pointer to exit the function,
      insert some code to save and restore the stack pointer.  */
--- gcc/testsuite/gcc.dg/pr87485.c.jj   2019-02-01 16:30:51.101211900 +0100
+++ gcc/testsuite/gcc.dg/pr87485.c      2019-02-01 16:31:48.660260183 +0100
@@ -0,0 +1,29 @@
+/* PR rtl-optimization/87485 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -fschedule-insns -fno-guess-branch-probability 
-fno-isolate-erroneous-paths-dereference -fno-omit-frame-pointer 
-fno-split-wide-types -fno-tree-ccp -fno-tree-sra" } */
+/* { dg-additional-options "-fstack-protector-strong" { target 
fstack_protector } } */
+
+int *a;
+
+int
+foo (__int128 x, int y, int z)
+{
+  __int128 b;
+  *a = ((!!y ? y : x) * y | x) * 2;
+  if (z == 0)
+    {
+      unsigned int c = 1;
+      __int128 *d = &b;
+      for (*a = 0; *a < 1; *a += y)
+       ;
+      *a += b < (c / 0);       /* { dg-warning "division by zero" } */
+      goto l;
+ m:
+      while (b < 1)
+       ;
+      ++*a;
+    }
+  goto m;
+ l:
+  return 0;
+}

        Jakub

Reply via email to