Hi.

We make direct emission for asan_emit_stack_protection for smaller stacks.
That's fine but we're missing the piece that marks the stack as released
and we run out of pre-allocated stacks. I also included some stack-related
constants that were used in asan.c.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

gcc/ChangeLog:

2020-05-19  Martin Liska  <mli...@suse.cz>

        PR sanitizer/94910
        * asan.c (asan_emit_stack_protection): Emit
        also **SavedFlagPtr(FakeStack) = 0 in order to release
        a stack frame.
        * asan.h (ASAN_MIN_STACK_FRAME_SIZE_LOG): New.
        (ASAN_MAX_STACK_FRAME_SIZE_LOG): Likewise.
        (ASAN_MIN_STACK_FRAME_SIZE): Likewise.
        (ASAN_MAX_STACK_FRAME_SIZE): Likewise.
---
 gcc/asan.c | 26 ++++++++++++++++++++++----
 gcc/asan.h |  8 ++++++++
 2 files changed, 30 insertions(+), 4 deletions(-)


diff --git a/gcc/asan.c b/gcc/asan.c
index c9872f1b007..4cdf294e82b 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1375,7 +1375,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   char buf[32];
   HOST_WIDE_INT base_offset = offsets[length - 1];
   HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
-  HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
+  unsigned HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
   HOST_WIDE_INT last_offset, last_size, last_size_aligned;
   int l;
   unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
@@ -1428,7 +1428,9 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   str_cst = asan_pp_string (&asan_pp);
 
   /* Emit the prologue sequence.  */
-  if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase
+  if (asan_frame_size >= ASAN_MIN_STACK_FRAME_SIZE
+      && asan_frame_size <= ASAN_MAX_STACK_FRAME_SIZE
+      && pbase
       && param_asan_use_after_return)
     {
       use_after_return_class = floor_log2 (asan_frame_size - 1) - 5;
@@ -1598,8 +1600,24 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
       if (use_after_return_class < 5
 	  && can_store_by_pieces (sz, builtin_memset_read_str, &c,
 				  BITS_PER_UNIT, true))
-	store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
-			 BITS_PER_UNIT, true, RETURN_BEGIN);
+	{
+	  /* Emit:
+	       memset(ShadowBase, kAsanStackAfterReturnMagic, ShadowSize);
+	       **SavedFlagPtr(FakeStack) = 0
+	  */
+	  store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
+			   BITS_PER_UNIT, true, RETURN_BEGIN);
+
+	  unsigned HOST_WIDE_INT offset
+	    = (1 << (use_after_return_class + ASAN_MIN_STACK_FRAME_SIZE_LOG));
+	  offset -= GET_MODE_SIZE (ptr_mode);
+	  mem = adjust_address (mem, Pmode, offset);
+	  mem = gen_rtx_MEM (ptr_mode, mem);
+	  rtx tmp_reg = gen_reg_rtx (Pmode);
+	  emit_move_insn (tmp_reg, mem);
+	  mem = adjust_address (mem, QImode, 0);
+	  emit_move_insn (mem, const0_rtx);
+	}
       else if (use_after_return_class >= 5
 	       || !set_storage_via_setmem (shadow_mem,
 					   GEN_INT (sz),
diff --git a/gcc/asan.h b/gcc/asan.h
index 9efd33f9b86..5ff0735045f 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -58,6 +58,14 @@ extern hash_set <tree> *asan_used_labels;
 
 #define ASAN_MIN_RED_ZONE_SIZE	16
 
+/* Minimal and maximal frame size for a fake stack frame.  */
+
+#define ASAN_MIN_STACK_FRAME_SIZE_LOG 6
+#define ASAN_MAX_STACK_FRAME_SIZE_LOG 16
+
+#define ASAN_MIN_STACK_FRAME_SIZE (1UL << ASAN_MIN_STACK_FRAME_SIZE_LOG)
+#define ASAN_MAX_STACK_FRAME_SIZE (1UL << ASAN_MAX_STACK_FRAME_SIZE_LOG)
+
 /* Shadow memory values for stack protection.  Left is below protected vars,
    the first pointer in stack corresponding to that offset contains
    ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing

Reply via email to