This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] Fix ICE in asan_clear_shadow (PR sanitizer/88291)


Hi!

On Sat, Dec 01, 2018 at 08:36:41AM +0100, Jakub Jelinek wrote:
> I'm still seeing some regressions, ICEs like:
> FAIL: c-c++-common/asan/clone-test-1.c   -O1  (internal compiler error)
> FAIL: c-c++-common/asan/clone-test-1.c   -O1  (test for excess errors)

And here is a fix for that.  It didn't trigger pretty much all the time
just because the assert in asan_clear_shadow has been added to an uncommon
spot, where clear_storage emits a libcall.

The patch makes sure that the offset is aligned to ASAN_RED_ZONE_SIZE
downward and size is padded up to make it a multiple of ASAN_RED_ZONE_SIZE
too.  E.g. on x86_64-linux we can emit rep; stosl instead of rep; stosb
this way etc.

Bootstrapped/regtested on x86_64-linux, i686-linux, powerpc64{,-le}-linux,
committed to trunk to unbreak asan on powerpc64.

2018-12-02  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/88291
	* asan.c (asan_clear_shadow): Move assert that len is multiple of 4
	to the start of the function.
	(asan_emit_stack_protection): When emitting clearing sequence for
	epilogue, align offset down to ASAN_RED_ZONE_SIZE granularity,
	add last_size_aligned which is last_size padded to multiples of
	ASAN_RED_ZONE_SIZE and emit asan_clear_shadow always on 4 byte
	boundaries.

	* c-c++-common/asan/pr88291.c: New test.

--- gcc/asan.c.jj	2018-12-01 08:31:30.000000000 +0100
+++ gcc/asan.c	2018-12-01 11:41:11.860166400 +0100
@@ -1165,6 +1165,7 @@ asan_clear_shadow (rtx shadow_mem, HOST_
   rtx_code_label *top_label;
   rtx end, addr, tmp;
 
+  gcc_assert ((len & 3) == 0);
   start_sequence ();
   clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
   insns = get_insns ();
@@ -1178,7 +1179,6 @@ asan_clear_shadow (rtx shadow_mem, HOST_
       return;
     }
 
-  gcc_assert ((len & 3) == 0);
   top_label = gen_label_rtx ();
   addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
   shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
@@ -1375,7 +1375,7 @@ asan_emit_stack_protection (rtx base, rt
   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;
-  HOST_WIDE_INT last_offset, last_size;
+  HOST_WIDE_INT last_offset, last_size, last_size_aligned;
   int l;
   unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
   tree str_cst, decl, id;
@@ -1628,20 +1628,23 @@ asan_emit_stack_protection (rtx base, rt
   prev_offset = base_offset;
   last_offset = base_offset;
   last_size = 0;
+  last_size_aligned = 0;
   for (l = length; l; l -= 2)
     {
       offset = base_offset + ((offsets[l - 1] - base_offset)
-			     & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
-      if (last_offset + last_size != offset)
+			      & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
+      if (last_offset + last_size_aligned < offset)
 	{
 	  shadow_mem = adjust_address (shadow_mem, VOIDmode,
 				       (last_offset - prev_offset)
 				       >> ASAN_SHADOW_SHIFT);
 	  prev_offset = last_offset;
-	  asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
+	  asan_clear_shadow (shadow_mem, last_size_aligned >> ASAN_SHADOW_SHIFT);
 	  last_offset = offset;
 	  last_size = 0;
 	}
+      else
+	last_size = offset - last_offset;
       last_size += base_offset + ((offsets[l - 2] - base_offset)
 				  & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
 		   - offset;
@@ -1667,13 +1670,16 @@ asan_emit_stack_protection (rtx base, rt
 		last_size += size & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
 	    }
 	}
+      last_size_aligned
+	= ((last_size + (ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
+	   & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
     }
-  if (last_size)
+  if (last_size_aligned)
     {
       shadow_mem = adjust_address (shadow_mem, VOIDmode,
 				   (last_offset - prev_offset)
 				   >> ASAN_SHADOW_SHIFT);
-      asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
+      asan_clear_shadow (shadow_mem, last_size_aligned >> ASAN_SHADOW_SHIFT);
     }
 
   /* Clean-up set with instrumented stack variables.  */
--- gcc/testsuite/c-c++-common/asan/pr88291.c.jj	2018-12-01 11:34:42.448549265 +0100
+++ gcc/testsuite/c-c++-common/asan/pr88291.c	2018-12-01 11:29:49.561348917 +0100
@@ -0,0 +1,14 @@
+/* PR sanitizer/88291 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=address -Os" } */
+/* { dg-additional-options "-mstringop-strategy=libcall" { target i?86-*-* x86_64-*-* } } */
+
+void bar (void *, void *);
+
+void
+foo (void)
+{
+  int b;
+  char __attribute__((aligned(16))) a[(1 << 20) + 1];
+  bar (&a, &b);
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]