diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-12-02 13:39:26 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-12-02 13:39:26 +0100 |
commit | e80944753d325ef009acf58a5b3188936997d22b (patch) | |
tree | 60c300b077aa69323c05bd819f079de56fc173cd /gcc/asan.c | |
parent | faa867f5a8b74b5eaef3066debc015dc888237cb (diff) | |
download | gcc-e80944753d325ef009acf58a5b3188936997d22b.tar.gz |
re PR sanitizer/88291 (asan ICE in asan_clear_shadow)
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.
From-SVN: r266721
Diffstat (limited to 'gcc/asan.c')
-rw-r--r-- | gcc/asan.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/gcc/asan.c b/gcc/asan.c index 0530ddd0056..98a42721f8f 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1165,6 +1165,7 @@ asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len) 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_WIDE_INT len) 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, rtx pbase, unsigned int alignb, 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, rtx pbase, unsigned int alignb, 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, rtx pbase, unsigned int alignb, 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. */ |