Hi! When asan unpoisons variables that don't have byte sizes that are multiples of 8, it on big endian stores the last chunk size value into the first byte rather than last byte, so e.g. for the variable of size 12 bytes in the testcase it stores half-word 0x0400 into the shadow memory, which is fine on little-endian (we want bytes 0x00 0x04), but wrong on big-endian. We don't support asan on pdp-endian targets.
Bootstrapped/regtested on powerpc64-linux, ok for trunk? 2017-04-05 Jakub Jelinek <ja...@redhat.com> Bernd Edlinger <bernd.edlin...@hotmail.de> PR sanitizer/80308 * asan.c (asan_store_shadow_bytes): Fix location of last_chunk_value for big endian. * c-c++-common/asan/pr80308.c: New test. --- gcc/asan.c.jj 2017-03-27 10:24:33.000000000 +0200 +++ gcc/asan.c 2017-04-05 08:19:00.512439980 +0200 @@ -2757,10 +2757,13 @@ asan_store_shadow_bytes (gimple_stmt_ite unsigned char c = (char) is_clobber ? ASAN_STACK_MAGIC_USE_AFTER_SCOPE : 0; unsigned HOST_WIDE_INT val = 0; + unsigned last_pos = size; + if (last_chunk_size && !is_clobber) + last_pos = BYTES_BIG_ENDIAN ? 0 : size - 1; for (unsigned i = 0; i < size; ++i) { unsigned char shadow_c = c; - if (i == size - 1 && last_chunk_size && !is_clobber) + if (i == last_pos) shadow_c = last_chunk_size; val |= (unsigned HOST_WIDE_INT) shadow_c << (BITS_PER_UNIT * i); } --- gcc/testsuite/c-c++-common/asan/pr80308.c.jj 2017-04-05 08:14:10.373364559 +0200 +++ gcc/testsuite/c-c++-common/asan/pr80308.c 2017-04-05 08:13:40.000000000 +0200 @@ -0,0 +1,25 @@ +/* PR sanitizer/80308 */ +/* { dg-do run } */ + +__attribute__((noinline, noclone)) int +foo (char *a) +{ + int i, j = 0; + asm volatile ("" : "+r" (a) : : "memory"); + for (i = 0; i < 12; i++) + j += a[i]; + return j; +} + +int +main () +{ + int i, j = 0; + for (i = 0; i < 4; i++) + { + char a[12]; + __builtin_memset (a, 0, sizeof (a)); + j += foo (a); + } + return j; +} Jakub