From 9e463823a8dbedb956fda93af75c206f9ef3acd4 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 9 Mar 2017 10:20:23 +0100 Subject: [PATCH] re PR sanitizer/79944 (asan: incorrect instrumentation of atomic operations) PR sanitizer/79944 * asan.c (get_mem_refs_of_builtin_call): For BUILT_IN_ATOMIC* and BUILT_IN_SYNC*, determine the access type from the size suffix and always build a MEM_REF with that type. Handle forgotten BUILT_IN_SYNC_FETCH_AND_NAND_16 and BUILT_IN_SYNC_NAND_AND_FETCH_16. * c-c++-common/asan/pr79944.c: New test. From-SVN: r245991 --- gcc/ChangeLog | 6 + gcc/asan.c | 318 +++++++++++----------- gcc/testsuite/ChangeLog | 3 + gcc/testsuite/c-c++-common/asan/pr79944.c | 18 ++ 4 files changed, 181 insertions(+), 164 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/asan/pr79944.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d85fe0e981..80d0aeaa6e4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2017-03-09 Jakub Jelinek + PR sanitizer/79944 + * asan.c (get_mem_refs_of_builtin_call): For BUILT_IN_ATOMIC* and + BUILT_IN_SYNC*, determine the access type from the size suffix and + always build a MEM_REF with that type. Handle forgotten + BUILT_IN_SYNC_FETCH_AND_NAND_16 and BUILT_IN_SYNC_NAND_AND_FETCH_16. + PR target/79932 * config/i386/avx512vlintrin.h (_mm256_cmpge_epi32_mask, _mm256_cmpge_epi64_mask, _mm256_cmpge_epu32_mask, diff --git a/gcc/asan.c b/gcc/asan.c index 7223e3cc68d..edcc6ea5a91 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -603,218 +603,208 @@ get_mem_refs_of_builtin_call (const gcall *call, case BUILT_IN_STRLEN: source0 = gimple_call_arg (call, 0); len = gimple_call_lhs (call); - break ; + break; /* And now the __atomic* and __sync builtins. These are handled differently from the classical memory memory access builtins above. */ case BUILT_IN_ATOMIC_LOAD_1: - case BUILT_IN_ATOMIC_LOAD_2: - case BUILT_IN_ATOMIC_LOAD_4: - case BUILT_IN_ATOMIC_LOAD_8: - case BUILT_IN_ATOMIC_LOAD_16: is_store = false; - /* fall through. */ - + /* FALLTHRU */ case BUILT_IN_SYNC_FETCH_AND_ADD_1: - case BUILT_IN_SYNC_FETCH_AND_ADD_2: - case BUILT_IN_SYNC_FETCH_AND_ADD_4: - case BUILT_IN_SYNC_FETCH_AND_ADD_8: - case BUILT_IN_SYNC_FETCH_AND_ADD_16: - case BUILT_IN_SYNC_FETCH_AND_SUB_1: - case BUILT_IN_SYNC_FETCH_AND_SUB_2: - case BUILT_IN_SYNC_FETCH_AND_SUB_4: - case BUILT_IN_SYNC_FETCH_AND_SUB_8: - case BUILT_IN_SYNC_FETCH_AND_SUB_16: - case BUILT_IN_SYNC_FETCH_AND_OR_1: - case BUILT_IN_SYNC_FETCH_AND_OR_2: - case BUILT_IN_SYNC_FETCH_AND_OR_4: - case BUILT_IN_SYNC_FETCH_AND_OR_8: - case BUILT_IN_SYNC_FETCH_AND_OR_16: - case BUILT_IN_SYNC_FETCH_AND_AND_1: - case BUILT_IN_SYNC_FETCH_AND_AND_2: - case BUILT_IN_SYNC_FETCH_AND_AND_4: - case BUILT_IN_SYNC_FETCH_AND_AND_8: - case BUILT_IN_SYNC_FETCH_AND_AND_16: - case BUILT_IN_SYNC_FETCH_AND_XOR_1: - case BUILT_IN_SYNC_FETCH_AND_XOR_2: - case BUILT_IN_SYNC_FETCH_AND_XOR_4: - case BUILT_IN_SYNC_FETCH_AND_XOR_8: - case BUILT_IN_SYNC_FETCH_AND_XOR_16: - case BUILT_IN_SYNC_FETCH_AND_NAND_1: - case BUILT_IN_SYNC_FETCH_AND_NAND_2: - case BUILT_IN_SYNC_FETCH_AND_NAND_4: - case BUILT_IN_SYNC_FETCH_AND_NAND_8: - case BUILT_IN_SYNC_ADD_AND_FETCH_1: - case BUILT_IN_SYNC_ADD_AND_FETCH_2: - case BUILT_IN_SYNC_ADD_AND_FETCH_4: - case BUILT_IN_SYNC_ADD_AND_FETCH_8: - case BUILT_IN_SYNC_ADD_AND_FETCH_16: - case BUILT_IN_SYNC_SUB_AND_FETCH_1: - case BUILT_IN_SYNC_SUB_AND_FETCH_2: - case BUILT_IN_SYNC_SUB_AND_FETCH_4: - case BUILT_IN_SYNC_SUB_AND_FETCH_8: - case BUILT_IN_SYNC_SUB_AND_FETCH_16: - case BUILT_IN_SYNC_OR_AND_FETCH_1: - case BUILT_IN_SYNC_OR_AND_FETCH_2: - case BUILT_IN_SYNC_OR_AND_FETCH_4: - case BUILT_IN_SYNC_OR_AND_FETCH_8: - case BUILT_IN_SYNC_OR_AND_FETCH_16: - case BUILT_IN_SYNC_AND_AND_FETCH_1: - case BUILT_IN_SYNC_AND_AND_FETCH_2: - case BUILT_IN_SYNC_AND_AND_FETCH_4: - case BUILT_IN_SYNC_AND_AND_FETCH_8: - case BUILT_IN_SYNC_AND_AND_FETCH_16: - case BUILT_IN_SYNC_XOR_AND_FETCH_1: - case BUILT_IN_SYNC_XOR_AND_FETCH_2: - case BUILT_IN_SYNC_XOR_AND_FETCH_4: - case BUILT_IN_SYNC_XOR_AND_FETCH_8: - case BUILT_IN_SYNC_XOR_AND_FETCH_16: - case BUILT_IN_SYNC_NAND_AND_FETCH_1: - case BUILT_IN_SYNC_NAND_AND_FETCH_2: - case BUILT_IN_SYNC_NAND_AND_FETCH_4: - case BUILT_IN_SYNC_NAND_AND_FETCH_8: - case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1: - case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2: - case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4: - case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8: - case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16: - case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1: - case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2: - case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4: - case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8: - case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16: - case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1: - case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2: - case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4: - case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8: - case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16: - case BUILT_IN_SYNC_LOCK_RELEASE_1: - case BUILT_IN_SYNC_LOCK_RELEASE_2: - case BUILT_IN_SYNC_LOCK_RELEASE_4: - case BUILT_IN_SYNC_LOCK_RELEASE_8: - case BUILT_IN_SYNC_LOCK_RELEASE_16: - case BUILT_IN_ATOMIC_EXCHANGE_1: - case BUILT_IN_ATOMIC_EXCHANGE_2: - case BUILT_IN_ATOMIC_EXCHANGE_4: - case BUILT_IN_ATOMIC_EXCHANGE_8: - case BUILT_IN_ATOMIC_EXCHANGE_16: - case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1: - case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2: - case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4: - case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8: - case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16: - case BUILT_IN_ATOMIC_STORE_1: - case BUILT_IN_ATOMIC_STORE_2: - case BUILT_IN_ATOMIC_STORE_4: - case BUILT_IN_ATOMIC_STORE_8: - case BUILT_IN_ATOMIC_STORE_16: - case BUILT_IN_ATOMIC_ADD_FETCH_1: - case BUILT_IN_ATOMIC_ADD_FETCH_2: - case BUILT_IN_ATOMIC_ADD_FETCH_4: - case BUILT_IN_ATOMIC_ADD_FETCH_8: - case BUILT_IN_ATOMIC_ADD_FETCH_16: - case BUILT_IN_ATOMIC_SUB_FETCH_1: - case BUILT_IN_ATOMIC_SUB_FETCH_2: - case BUILT_IN_ATOMIC_SUB_FETCH_4: - case BUILT_IN_ATOMIC_SUB_FETCH_8: - case BUILT_IN_ATOMIC_SUB_FETCH_16: - case BUILT_IN_ATOMIC_AND_FETCH_1: - case BUILT_IN_ATOMIC_AND_FETCH_2: - case BUILT_IN_ATOMIC_AND_FETCH_4: - case BUILT_IN_ATOMIC_AND_FETCH_8: - case BUILT_IN_ATOMIC_AND_FETCH_16: - case BUILT_IN_ATOMIC_NAND_FETCH_1: - case BUILT_IN_ATOMIC_NAND_FETCH_2: - case BUILT_IN_ATOMIC_NAND_FETCH_4: - case BUILT_IN_ATOMIC_NAND_FETCH_8: - case BUILT_IN_ATOMIC_NAND_FETCH_16: - case BUILT_IN_ATOMIC_XOR_FETCH_1: - case BUILT_IN_ATOMIC_XOR_FETCH_2: - case BUILT_IN_ATOMIC_XOR_FETCH_4: - case BUILT_IN_ATOMIC_XOR_FETCH_8: - case BUILT_IN_ATOMIC_XOR_FETCH_16: - case BUILT_IN_ATOMIC_OR_FETCH_1: - case BUILT_IN_ATOMIC_OR_FETCH_2: - case BUILT_IN_ATOMIC_OR_FETCH_4: - case BUILT_IN_ATOMIC_OR_FETCH_8: - case BUILT_IN_ATOMIC_OR_FETCH_16: - case BUILT_IN_ATOMIC_FETCH_ADD_1: - case BUILT_IN_ATOMIC_FETCH_ADD_2: - case BUILT_IN_ATOMIC_FETCH_ADD_4: - case BUILT_IN_ATOMIC_FETCH_ADD_8: - case BUILT_IN_ATOMIC_FETCH_ADD_16: - case BUILT_IN_ATOMIC_FETCH_SUB_1: - case BUILT_IN_ATOMIC_FETCH_SUB_2: - case BUILT_IN_ATOMIC_FETCH_SUB_4: - case BUILT_IN_ATOMIC_FETCH_SUB_8: - case BUILT_IN_ATOMIC_FETCH_SUB_16: - case BUILT_IN_ATOMIC_FETCH_AND_1: - case BUILT_IN_ATOMIC_FETCH_AND_2: - case BUILT_IN_ATOMIC_FETCH_AND_4: - case BUILT_IN_ATOMIC_FETCH_AND_8: - case BUILT_IN_ATOMIC_FETCH_AND_16: - case BUILT_IN_ATOMIC_FETCH_NAND_1: - case BUILT_IN_ATOMIC_FETCH_NAND_2: - case BUILT_IN_ATOMIC_FETCH_NAND_4: - case BUILT_IN_ATOMIC_FETCH_NAND_8: - case BUILT_IN_ATOMIC_FETCH_NAND_16: - case BUILT_IN_ATOMIC_FETCH_XOR_1: - case BUILT_IN_ATOMIC_FETCH_XOR_2: - case BUILT_IN_ATOMIC_FETCH_XOR_4: - case BUILT_IN_ATOMIC_FETCH_XOR_8: - case BUILT_IN_ATOMIC_FETCH_XOR_16: - case BUILT_IN_ATOMIC_FETCH_OR_1: + access_size = 1; + goto do_atomic; + + case BUILT_IN_ATOMIC_LOAD_2: + is_store = false; + /* FALLTHRU */ + case BUILT_IN_SYNC_FETCH_AND_ADD_2: + case BUILT_IN_SYNC_FETCH_AND_SUB_2: + case BUILT_IN_SYNC_FETCH_AND_OR_2: + case BUILT_IN_SYNC_FETCH_AND_AND_2: + case BUILT_IN_SYNC_FETCH_AND_XOR_2: + case BUILT_IN_SYNC_FETCH_AND_NAND_2: + case BUILT_IN_SYNC_ADD_AND_FETCH_2: + case BUILT_IN_SYNC_SUB_AND_FETCH_2: + case BUILT_IN_SYNC_OR_AND_FETCH_2: + case BUILT_IN_SYNC_AND_AND_FETCH_2: + case BUILT_IN_SYNC_XOR_AND_FETCH_2: + case BUILT_IN_SYNC_NAND_AND_FETCH_2: + case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2: + case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2: + case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2: + case BUILT_IN_SYNC_LOCK_RELEASE_2: + case BUILT_IN_ATOMIC_EXCHANGE_2: + case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2: + case BUILT_IN_ATOMIC_STORE_2: + case BUILT_IN_ATOMIC_ADD_FETCH_2: + case BUILT_IN_ATOMIC_SUB_FETCH_2: + case BUILT_IN_ATOMIC_AND_FETCH_2: + case BUILT_IN_ATOMIC_NAND_FETCH_2: + case BUILT_IN_ATOMIC_XOR_FETCH_2: + case BUILT_IN_ATOMIC_OR_FETCH_2: + case BUILT_IN_ATOMIC_FETCH_ADD_2: + case BUILT_IN_ATOMIC_FETCH_SUB_2: + case BUILT_IN_ATOMIC_FETCH_AND_2: + case BUILT_IN_ATOMIC_FETCH_NAND_2: + case BUILT_IN_ATOMIC_FETCH_XOR_2: case BUILT_IN_ATOMIC_FETCH_OR_2: + access_size = 2; + goto do_atomic; + + case BUILT_IN_ATOMIC_LOAD_4: + is_store = false; + /* FALLTHRU */ + case BUILT_IN_SYNC_FETCH_AND_ADD_4: + case BUILT_IN_SYNC_FETCH_AND_SUB_4: + case BUILT_IN_SYNC_FETCH_AND_OR_4: + case BUILT_IN_SYNC_FETCH_AND_AND_4: + case BUILT_IN_SYNC_FETCH_AND_XOR_4: + case BUILT_IN_SYNC_FETCH_AND_NAND_4: + case BUILT_IN_SYNC_ADD_AND_FETCH_4: + case BUILT_IN_SYNC_SUB_AND_FETCH_4: + case BUILT_IN_SYNC_OR_AND_FETCH_4: + case BUILT_IN_SYNC_AND_AND_FETCH_4: + case BUILT_IN_SYNC_XOR_AND_FETCH_4: + case BUILT_IN_SYNC_NAND_AND_FETCH_4: + case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4: + case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4: + case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4: + case BUILT_IN_SYNC_LOCK_RELEASE_4: + case BUILT_IN_ATOMIC_EXCHANGE_4: + case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4: + case BUILT_IN_ATOMIC_STORE_4: + case BUILT_IN_ATOMIC_ADD_FETCH_4: + case BUILT_IN_ATOMIC_SUB_FETCH_4: + case BUILT_IN_ATOMIC_AND_FETCH_4: + case BUILT_IN_ATOMIC_NAND_FETCH_4: + case BUILT_IN_ATOMIC_XOR_FETCH_4: + case BUILT_IN_ATOMIC_OR_FETCH_4: + case BUILT_IN_ATOMIC_FETCH_ADD_4: + case BUILT_IN_ATOMIC_FETCH_SUB_4: + case BUILT_IN_ATOMIC_FETCH_AND_4: + case BUILT_IN_ATOMIC_FETCH_NAND_4: + case BUILT_IN_ATOMIC_FETCH_XOR_4: case BUILT_IN_ATOMIC_FETCH_OR_4: + access_size = 4; + goto do_atomic; + + case BUILT_IN_ATOMIC_LOAD_8: + is_store = false; + /* FALLTHRU */ + case BUILT_IN_SYNC_FETCH_AND_ADD_8: + case BUILT_IN_SYNC_FETCH_AND_SUB_8: + case BUILT_IN_SYNC_FETCH_AND_OR_8: + case BUILT_IN_SYNC_FETCH_AND_AND_8: + case BUILT_IN_SYNC_FETCH_AND_XOR_8: + case BUILT_IN_SYNC_FETCH_AND_NAND_8: + case BUILT_IN_SYNC_ADD_AND_FETCH_8: + case BUILT_IN_SYNC_SUB_AND_FETCH_8: + case BUILT_IN_SYNC_OR_AND_FETCH_8: + case BUILT_IN_SYNC_AND_AND_FETCH_8: + case BUILT_IN_SYNC_XOR_AND_FETCH_8: + case BUILT_IN_SYNC_NAND_AND_FETCH_8: + case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8: + case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8: + case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8: + case BUILT_IN_SYNC_LOCK_RELEASE_8: + case BUILT_IN_ATOMIC_EXCHANGE_8: + case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8: + case BUILT_IN_ATOMIC_STORE_8: + case BUILT_IN_ATOMIC_ADD_FETCH_8: + case BUILT_IN_ATOMIC_SUB_FETCH_8: + case BUILT_IN_ATOMIC_AND_FETCH_8: + case BUILT_IN_ATOMIC_NAND_FETCH_8: + case BUILT_IN_ATOMIC_XOR_FETCH_8: + case BUILT_IN_ATOMIC_OR_FETCH_8: + case BUILT_IN_ATOMIC_FETCH_ADD_8: + case BUILT_IN_ATOMIC_FETCH_SUB_8: + case BUILT_IN_ATOMIC_FETCH_AND_8: + case BUILT_IN_ATOMIC_FETCH_NAND_8: + case BUILT_IN_ATOMIC_FETCH_XOR_8: case BUILT_IN_ATOMIC_FETCH_OR_8: + access_size = 8; + goto do_atomic; + + case BUILT_IN_ATOMIC_LOAD_16: + is_store = false; + /* FALLTHRU */ + case BUILT_IN_SYNC_FETCH_AND_ADD_16: + case BUILT_IN_SYNC_FETCH_AND_SUB_16: + case BUILT_IN_SYNC_FETCH_AND_OR_16: + case BUILT_IN_SYNC_FETCH_AND_AND_16: + case BUILT_IN_SYNC_FETCH_AND_XOR_16: + case BUILT_IN_SYNC_FETCH_AND_NAND_16: + case BUILT_IN_SYNC_ADD_AND_FETCH_16: + case BUILT_IN_SYNC_SUB_AND_FETCH_16: + case BUILT_IN_SYNC_OR_AND_FETCH_16: + case BUILT_IN_SYNC_AND_AND_FETCH_16: + case BUILT_IN_SYNC_XOR_AND_FETCH_16: + case BUILT_IN_SYNC_NAND_AND_FETCH_16: + case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16: + case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16: + case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16: + case BUILT_IN_SYNC_LOCK_RELEASE_16: + case BUILT_IN_ATOMIC_EXCHANGE_16: + case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16: + case BUILT_IN_ATOMIC_STORE_16: + case BUILT_IN_ATOMIC_ADD_FETCH_16: + case BUILT_IN_ATOMIC_SUB_FETCH_16: + case BUILT_IN_ATOMIC_AND_FETCH_16: + case BUILT_IN_ATOMIC_NAND_FETCH_16: + case BUILT_IN_ATOMIC_XOR_FETCH_16: + case BUILT_IN_ATOMIC_OR_FETCH_16: + case BUILT_IN_ATOMIC_FETCH_ADD_16: + case BUILT_IN_ATOMIC_FETCH_SUB_16: + case BUILT_IN_ATOMIC_FETCH_AND_16: + case BUILT_IN_ATOMIC_FETCH_NAND_16: + case BUILT_IN_ATOMIC_FETCH_XOR_16: case BUILT_IN_ATOMIC_FETCH_OR_16: + access_size = 16; + /* FALLTHRU */ + do_atomic: { dest = gimple_call_arg (call, 0); /* DEST represents the address of a memory location. instrument_derefs wants the memory location, so lets dereference the address DEST before handing it to instrument_derefs. */ - if (TREE_CODE (dest) == ADDR_EXPR) - dest = TREE_OPERAND (dest, 0); - else if (TREE_CODE (dest) == SSA_NAME || TREE_CODE (dest) == INTEGER_CST) - dest = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (dest)), - dest, build_int_cst (TREE_TYPE (dest), 0)); - else - gcc_unreachable (); - - access_size = int_size_in_bytes (TREE_TYPE (dest)); + tree type = build_nonstandard_integer_type (access_size + * BITS_PER_UNIT, 1); + dest = build2 (MEM_REF, type, dest, + build_int_cst (build_pointer_type (char_type_node), 0)); + break; } default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 45839d25ddc..13218ac30eb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2017-03-09 Jakub Jelinek + PR sanitizer/79944 + * c-c++-common/asan/pr79944.c: New test. + PR target/79932 * gcc.target/i386/pr79932-2.c: New test. diff --git a/gcc/testsuite/c-c++-common/asan/pr79944.c b/gcc/testsuite/c-c++-common/asan/pr79944.c new file mode 100644 index 00000000000..62c56981b20 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr79944.c @@ -0,0 +1,18 @@ +/* PR sanitizer/79944 */ +/* { dg-do run } */ + +struct S { int i; char p[1024]; }; + +int +main () +{ + struct S *p = (struct S *) __builtin_malloc (__builtin_offsetof (struct S, p) + 64); + p->i = 5; + asm volatile ("" : "+r" (p) : : "memory"); + __atomic_fetch_add ((int *) p, 5, __ATOMIC_RELAXED); + asm volatile ("" : "+r" (p) : : "memory"); + if (p->i != 10) + __builtin_abort (); + __builtin_free (p); + return 0; +} -- 2.30.2