> 3. The GCC estimate itself is also fixable (make account_stack_vars()
>    add the redzones it is going to allocate anyway, ~30 lines in
>    cfgexpand.cc). That reduces total KASAN stack usage by ~7% for
>    +0.35% text and fixes this particular case on its own (704 -> 368),
>    so it is probably worth upstreaming. But it is a correctness fix, not a
>    cure: it doesn't change the number of frames above 1024/2048 at all.

For what it's worth, the patch looks like this:

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 0261f861b..56e335cb2 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -1653,12 +1653,17 @@ expand_stack_vars (bool (*pred) (unsigned),
class stack_vars_data *data)
   gcc_assert (known_eq (large_alloc, large_size));
 }

-/* Take into account all sizes of partitions and reset DECL_RTLs.  */
+/* Take into account all sizes of partitions and reset DECL_RTLs.
+   When the stack is sanitized by ASan, account for the red zones that
+   expand_stack_vars will later allocate around each protected variable,
+   so that the inliner's stack size estimate is not wildly optimistic.  */
 static poly_uint64
 account_stack_vars (void)
 {
   unsigned si, j, i, n = stack_vars_num;
   poly_uint64 size = 0;
+  bool asan_vars = false;
+  bool asan_p = asan_sanitize_stack_p ();

   for (si = 0; si < n; ++si)
     {
@@ -1668,10 +1673,32 @@ account_stack_vars (void)
       if (stack_vars[i].representative != i)
  continue;

-      size += stack_vars[i].size;
+      poly_uint64 vsize = stack_vars[i].size;
+      unsigned HOST_WIDE_INT csize;
+      if (asan_p
+  && vsize.is_constant (&csize)
+  && stack_vars[i].alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
+ {
+  bool prot = false;
+  for (j = i; j != EOC; j = stack_vars[j].next)
+    if (asan_protect_stack_decl (stack_vars[j].decl))
+      {
+ prot = true;
+ break;
+      }
+  if (prot)
+    {
+      vsize = asan_var_and_redzone_size (csize);
+      asan_vars = true;
+    }
+ }
+      size += vsize;
       for (j = i; j != EOC; j = stack_vars[j].next)
  set_rtl (stack_vars[j].decl, NULL);
     }
+  /* Leading red zone of the ASan protected frame region.  */
+  if (asan_vars)
+    size += ASAN_RED_ZONE_SIZE;
   return size;
 }

Reply via email to