From a47850552a0a25db7793a4eaf4859d43368a8b65 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Wed, 25 Nov 2020 16:31:49 +0000 Subject: [PATCH] libsanitizer: Add tests Only interesting thing here is that we have to make sure the tagging mechanism is deterministic to avoid flaky tests. gcc/testsuite/ChangeLog: * c-c++-common/ubsan/sanitize-recover-7.c: Update error message format. * lib/asan-dg.exp (asan_link_flags): Implement as a helper function asan_link_flags_1 which asan_link_flags and hwasan_link_flags use. (asan_link_flags_1): Parametrised version of asan_link_flags. * c-c++-common/hwasan/aligned-alloc.c: New test. * c-c++-common/hwasan/alloca-array-accessible.c: New test. * c-c++-common/hwasan/alloca-base-init.c: New test. * c-c++-common/hwasan/alloca-gets-different-tag.c: New test. * c-c++-common/hwasan/alloca-outside-caught.c: New test. * c-c++-common/hwasan/arguments-1.c: New test. * c-c++-common/hwasan/arguments-2.c: New test. * c-c++-common/hwasan/arguments-3.c: New test. * c-c++-common/hwasan/arguments.c: New test. * c-c++-common/hwasan/asan-pr63316.c: New test. * c-c++-common/hwasan/asan-pr70541.c: New test. * c-c++-common/hwasan/asan-pr78106.c: New test. * c-c++-common/hwasan/asan-pr79944.c: New test. * c-c++-common/hwasan/asan-rlimit-mmap-test-1.c: New test. * c-c++-common/hwasan/bitfield-1.c: New test. * c-c++-common/hwasan/bitfield-2.c: New test. * c-c++-common/hwasan/builtin-special-handling.c: New test. * c-c++-common/hwasan/check-interface.c: New test. * c-c++-common/hwasan/halt_on_error-1.c: New test. * c-c++-common/hwasan/handles-poly_int-marked-vars.c: New test. * c-c++-common/hwasan/heap-overflow.c: New test. * c-c++-common/hwasan/hwasan-poison-optimisation.c: New test. * c-c++-common/hwasan/hwasan-thread-access-parent.c: New test. * c-c++-common/hwasan/hwasan-thread-basic-failure.c: New test. * c-c++-common/hwasan/hwasan-thread-clears-stack.c: New test. * c-c++-common/hwasan/hwasan-thread-success.c: New test. * c-c++-common/hwasan/kernel-defaults.c: New test. * c-c++-common/hwasan/large-aligned-0.c: New test. * c-c++-common/hwasan/large-aligned-1.c: New test. * c-c++-common/hwasan/large-aligned-untagging-0.c: New test. * c-c++-common/hwasan/large-aligned-untagging-1.c: New test. * c-c++-common/hwasan/large-aligned-untagging-2.c: New test. * c-c++-common/hwasan/large-aligned-untagging-3.c: New test. * c-c++-common/hwasan/large-aligned-untagging-4.c: New test. * c-c++-common/hwasan/large-aligned-untagging-5.c: New test. * c-c++-common/hwasan/large-aligned-untagging-6.c: New test. * c-c++-common/hwasan/large-aligned-untagging-7.c: New test. * c-c++-common/hwasan/macro-definition.c: New test. * c-c++-common/hwasan/no-sanitize-attribute.c: New test. * c-c++-common/hwasan/param-instrument-mem-intrinsics.c: New test. * c-c++-common/hwasan/param-instrument-reads-and-writes.c: New test. * c-c++-common/hwasan/param-instrument-reads.c: New test. * c-c++-common/hwasan/param-instrument-writes.c: New test. * c-c++-common/hwasan/random-frame-tag.c: New test. * c-c++-common/hwasan/sanity-check-pure-c.c: New test. * c-c++-common/hwasan/setjmp-longjmp-0.c: New test. * c-c++-common/hwasan/setjmp-longjmp-1.c: New test. * c-c++-common/hwasan/stack-tagging-basic-0.c: New test. * c-c++-common/hwasan/stack-tagging-basic-1.c: New test. * c-c++-common/hwasan/stack-tagging-disable.c: New test. * c-c++-common/hwasan/unprotected-allocas-0.c: New test. * c-c++-common/hwasan/unprotected-allocas-1.c: New test. * c-c++-common/hwasan/use-after-free.c: New test. * c-c++-common/hwasan/vararray-outside-caught.c: New test. * c-c++-common/hwasan/vararray-stack-restore-correct.c: New test. * c-c++-common/hwasan/very-large-objects.c: New test. * g++.dg/hwasan/hwasan.exp: New test. * g++.dg/hwasan/rvo-handled.C: New test. * gcc.dg/hwasan/hwasan.exp: New test. * gcc.dg/hwasan/nested-functions-0.c: New test. * gcc.dg/hwasan/nested-functions-1.c: New test. * gcc.dg/hwasan/nested-functions-2.c: New test. * lib/hwasan-dg.exp: New file. --- .../c-c++-common/hwasan/aligned-alloc.c | 16 ++ .../hwasan/alloca-array-accessible.c | 33 ++++ .../c-c++-common/hwasan/alloca-base-init.c | 66 ++++++++ .../hwasan/alloca-gets-different-tag.c | 65 ++++++++ .../hwasan/alloca-outside-caught.c | 25 +++ .../c-c++-common/hwasan/arguments-1.c | 3 + .../c-c++-common/hwasan/arguments-2.c | 3 + .../c-c++-common/hwasan/arguments-3.c | 3 + gcc/testsuite/c-c++-common/hwasan/arguments.c | 3 + .../c-c++-common/hwasan/asan-pr63316.c | 24 +++ .../c-c++-common/hwasan/asan-pr70541.c | 36 +++++ .../c-c++-common/hwasan/asan-pr78106.c | 31 ++++ .../c-c++-common/hwasan/asan-pr79944.c | 19 +++ .../hwasan/asan-rlimit-mmap-test-1.c | 24 +++ .../c-c++-common/hwasan/bitfield-1.c | 31 ++++ .../c-c++-common/hwasan/bitfield-2.c | 30 ++++ .../hwasan/builtin-special-handling.c | 31 ++++ .../c-c++-common/hwasan/check-interface.c | 26 +++ .../c-c++-common/hwasan/halt_on_error-1.c | 24 +++ .../hwasan/handles-poly_int-marked-vars.c | 37 +++++ .../c-c++-common/hwasan/heap-overflow.c | 29 ++++ .../hwasan/hwasan-poison-optimisation.c | 29 ++++ .../hwasan/hwasan-thread-access-parent.c | 51 ++++++ .../hwasan/hwasan-thread-basic-failure.c | 48 ++++++ .../hwasan/hwasan-thread-clears-stack.c | 56 +++++++ .../hwasan/hwasan-thread-success.c | 35 ++++ .../c-c++-common/hwasan/kernel-defaults.c | 37 +++++ .../c-c++-common/hwasan/large-aligned-0.c | 33 ++++ .../c-c++-common/hwasan/large-aligned-1.c | 14 ++ .../hwasan/large-aligned-untagging-0.c | 75 +++++++++ .../hwasan/large-aligned-untagging-1.c | 15 ++ .../hwasan/large-aligned-untagging-2.c | 15 ++ .../hwasan/large-aligned-untagging-3.c | 15 ++ .../hwasan/large-aligned-untagging-4.c | 16 ++ .../hwasan/large-aligned-untagging-5.c | 16 ++ .../hwasan/large-aligned-untagging-6.c | 16 ++ .../hwasan/large-aligned-untagging-7.c | 16 ++ .../c-c++-common/hwasan/macro-definition.c | 11 ++ .../hwasan/no-sanitize-attribute.c | 12 ++ .../hwasan/param-instrument-mem-intrinsics.c | 10 ++ .../param-instrument-reads-and-writes.c | 7 + .../hwasan/param-instrument-reads.c | 21 +++ .../hwasan/param-instrument-writes.c | 7 + .../c-c++-common/hwasan/random-frame-tag.c | 7 + .../c-c++-common/hwasan/sanity-check-pure-c.c | 25 +++ .../c-c++-common/hwasan/setjmp-longjmp-0.c | 54 +++++++ .../c-c++-common/hwasan/setjmp-longjmp-1.c | 19 +++ .../hwasan/stack-tagging-basic-0.c | 37 +++++ .../hwasan/stack-tagging-basic-1.c | 18 +++ .../hwasan/stack-tagging-disable.c | 33 ++++ .../hwasan/unprotected-allocas-0.c | 46 ++++++ .../hwasan/unprotected-allocas-1.c | 16 ++ .../c-c++-common/hwasan/use-after-free.c | 28 ++++ .../hwasan/vararray-outside-caught.c | 22 +++ .../hwasan/vararray-stack-restore-correct.c | 43 +++++ .../c-c++-common/hwasan/very-large-objects.c | 68 ++++++++ .../c-c++-common/ubsan/sanitize-recover-7.c | 2 +- gcc/testsuite/g++.dg/hwasan/hwasan.exp | 34 ++++ gcc/testsuite/g++.dg/hwasan/rvo-handled.C | 46 ++++++ gcc/testsuite/gcc.dg/hwasan/hwasan.exp | 36 +++++ .../gcc.dg/hwasan/nested-functions-0.c | 53 +++++++ .../gcc.dg/hwasan/nested-functions-1.c | 27 ++++ .../gcc.dg/hwasan/nested-functions-2.c | 28 ++++ gcc/testsuite/lib/asan-dg.exp | 31 ++-- gcc/testsuite/lib/hwasan-dg.exp | 150 ++++++++++++++++++ 65 files changed, 1924 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/arguments-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/arguments-2.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/arguments-3.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/arguments.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/bitfield-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/bitfield-2.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/check-interface.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/heap-overflow.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/macro-definition.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/use-after-free.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c create mode 100644 gcc/testsuite/c-c++-common/hwasan/very-large-objects.c create mode 100644 gcc/testsuite/g++.dg/hwasan/hwasan.exp create mode 100644 gcc/testsuite/g++.dg/hwasan/rvo-handled.C create mode 100644 gcc/testsuite/gcc.dg/hwasan/hwasan.exp create mode 100644 gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c create mode 100644 gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c create mode 100644 gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c create mode 100644 gcc/testsuite/lib/hwasan-dg.exp diff --git a/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c new file mode 100644 index 00000000000..d38b1f3f62d --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* This program fails at runtime in the libhwasan library. + The allocator can't handle the requested invalid alignment. */ + +int +main () +{ + void *p = __builtin_aligned_alloc (17, 100); + if (((unsigned long long)p & 0x10) == 0) + return 0; + return 1; +} + +/* { dg-output "HWAddressSanitizer: invalid alignment requested in aligned_alloc: 17" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c new file mode 100644 index 00000000000..5e4c168f77e --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +#define alloca __builtin_alloca + +int __attribute__ ((noinline)) +using_alloca (int num) +{ + int retval = 0; + int *big_array = (int*)alloca (num * sizeof (int)); + for (int i = 0; i < num; ++i) { + retval += big_array[i]; + } + return retval; +} + +int __attribute__ ((noinline)) +using_vararray (int num) +{ + int retval = 0; + int big_array[num]; + for (int i = 0; i < num; ++i) { + retval += big_array[i]; + } + return retval; +} + +int main() +{ + using_alloca (16); + using_vararray (12); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c b/gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c new file mode 100644 index 00000000000..3ebeaa0b9e2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/alloca-base-init.c @@ -0,0 +1,66 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-additional-options "--param hwasan-random-frame-tag=1" } */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ +#include + +/* This testcase checks that `alloca` calls ensure the `__hwasan_generate_tag` + function is called to initialize the base tag. `alloca` calls are treated + differently to standard variables. The prologue/epilogue sequence is + generated mainly based on normal stack-allocated objects. + + We want to ensure that though the `alloca` call is not poisoned/unpoisoned + by the prologue and epilogue, the use of them in a given function still + triggers the prologue sequence to emit a call to __hwasan_generate_tag (and + hence that any call to __hwasan_generate_tag is emitted in the unconditional + part of the function code). */ + +int choice = 0; +int record = 1; + +#ifdef __cplusplus +extern "C" { +#endif +__attribute__ ((noinline)) +unsigned char +__hwasan_generate_tag () +{ + record = 0; + return 3; +} +#ifdef __cplusplus +} +#endif + +__attribute__ ((noinline)) +int +generate_tag_was_missed (void) +{ + return record; +} + +__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 () +{ + if (choice) + { + char *x = (char *)alloca(100); + foo(x); + } + else + { + char *y = (char *)alloca(20); + foo(y); + } + return generate_tag_was_missed (); +} diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c b/gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c new file mode 100644 index 00000000000..e83734f4b79 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/alloca-gets-different-tag.c @@ -0,0 +1,65 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +/* Alloca is given a different tag to other variables. + vararray should behave in the same way. */ + +#define alloca __builtin_alloca +#define assert(x) if (!(x)) __builtin_abort () + +struct two_values { + int left; + int right; +}; + +/* Require default hwasan tag ABI. + Know we're using AArch64 since that's the only architecture we run hwasan + tests on. */ +char tag_of (void * x) { return ((unsigned long long)x) >> 56; } + +int __attribute__ ((noinline)) +alloca_different_tag (int num) +{ + struct two_values tmp_object = { + .left = 100, + .right = num, + }; + int *big_array = (int *)alloca (num * sizeof (int)); + int other_array[100]; + + char first_tag = tag_of (&tmp_object); + char second_tag = tag_of (big_array); + char other_tag = tag_of (other_array); + assert (first_tag != second_tag); + assert (second_tag != other_tag); + assert (first_tag != other_tag); + return 0; +} + +int __attribute__ ((noinline)) +vararray_different_tag (int num) +{ + struct two_values tmp_object = { + .left = 100, + .right = num, + }; + int big_array[num]; + int other_array[100]; + + char first_tag = tag_of (&tmp_object); + char second_tag = tag_of (big_array); + char other_tag = tag_of (other_array); + assert (first_tag != second_tag); + assert (second_tag != other_tag); + assert (first_tag != other_tag); + return 0; +} + +int __attribute__ ((noinline)) +main () +{ + alloca_different_tag (10); + vararray_different_tag (8); + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c b/gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c new file mode 100644 index 00000000000..60d7a9a874f --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/alloca-outside-caught.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +#define alloca __builtin_alloca + +int __attribute__ ((noinline)) +check_alloca (int num) +{ + volatile int *allocd_array = (int*)alloca (num * sizeof(int)); + int other_array[10]; + return allocd_array[12]; +} + +int __attribute__ ((noinline)) +main () +{ + check_alloca (3); + return 1; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments-1.c b/gcc/testsuite/c-c++-common/hwasan/arguments-1.c new file mode 100644 index 00000000000..435dad3cf15 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/arguments-1.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fsanitize=kernel-hwaddress" } */ +/* { dg-error ".*'-fsanitize=hwaddress' is incompatible with '-fsanitize=kernel-hwaddress'.*" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments-2.c b/gcc/testsuite/c-c++-common/hwasan/arguments-2.c new file mode 100644 index 00000000000..fafde99a05a --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/arguments-2.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fsanitize=kernel-address" } */ +/* { dg-error ".*'-fsanitize=hwaddress' is incompatible with '-fsanitize=kernel-address'.*" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments-3.c b/gcc/testsuite/c-c++-common/hwasan/arguments-3.c new file mode 100644 index 00000000000..6e907b46b3b --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/arguments-3.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fsanitize=thread" } */ +/* { dg-error ".*'-fsanitize=thread' is incompatible with '-fsanitize=hwaddress'.*" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments.c b/gcc/testsuite/c-c++-common/hwasan/arguments.c new file mode 100644 index 00000000000..7c113149179 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/arguments.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fsanitize=address" } */ +/* { dg-error ".*'-fsanitize=hwaddress' is incompatible with '-fsanitize=address'.*" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c new file mode 100644 index 00000000000..dd3b3dbf225 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr63316.c @@ -0,0 +1,24 @@ +/* PR sanitizer/63316 */ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ + +#ifdef __cplusplus +extern "C" { +#endif +extern void *malloc (__SIZE_TYPE__); +extern void free (void *); +#ifdef __cplusplus +} +#endif + +int +main () +{ + int *p = (int *) malloc (sizeof (int)); + *p = 3; + asm volatile ("" : : "r" (p) : "memory"); + free (p); + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c new file mode 100644 index 00000000000..ba2ed496e6e --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr70541.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ +/* { dg-shouldfail "hwasan" } */ + +#include +#ifdef __cplusplus +extern "C" { +#endif +extern void *malloc (__SIZE_TYPE__); +extern void free (void *); +#ifdef __cplusplus +} +#endif + +struct Simple { + int value; +}; + +int f(struct Simple simple) { + return simple.value; +} + +int main() { + struct Simple *psimple = (struct Simple *) malloc(sizeof(struct Simple)); + psimple->value = 42; + free(psimple); + printf("%d\n", f(*psimple)); + return 0; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "freed by thread T0 here:.*" } */ +/* { dg-output "previously allocated here:" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c new file mode 100644 index 00000000000..3f53ad17693 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr78106.c @@ -0,0 +1,31 @@ +/* PR sanitizer/78106 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=hwaddress -fdump-tree-sanopt-details -ffat-lto-objects" } */ + +int *variable; + +void __attribute__((used)) release() +{ + __builtin_free (variable); +} + +int main2(int argc) +{ + *variable = 2; + + if (argc <= 5) + asm volatile ("call release"); + + *variable = 2; + __builtin_abort (); + + return 0; +} + +int main(int argc, char **argv) +{ + variable = (int *)__builtin_malloc (sizeof(int)); + return main2(argc); +} + +/* { dg-final { scan-tree-dump-not "Optimizing out(\n|\r\n|\r) HWASAN_CHECK \\(7, variable.*" "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c b/gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c new file mode 100644 index 00000000000..7d54f54701b --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/asan-pr79944.c @@ -0,0 +1,19 @@ +/* PR sanitizer/79944 */ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +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; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c b/gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c new file mode 100644 index 00000000000..5426b8ab430 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/asan-rlimit-mmap-test-1.c @@ -0,0 +1,24 @@ +/* Check that we properly report mmap failure. */ + +/* { dg-do run { target setrlimit } } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ +/* { dg-require-effective-target hw } */ +/* { dg-shouldfail "hwasan" } */ + +#include +#include +#include +#include + +static volatile void *x; + +int main(int argc, char **argv) { + struct rlimit mmap_resource_limit = { 0, 0 }; + if (setrlimit(RLIMIT_AS, &mmap_resource_limit)) return 1; + x = malloc(10000000); + return 0; +} + +/* { dg-output "ERROR: Failed to mmap" } */ + diff --git a/gcc/testsuite/c-c++-common/hwasan/bitfield-1.c b/gcc/testsuite/c-c++-common/hwasan/bitfield-1.c new file mode 100644 index 00000000000..0c3479eacc4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/bitfield-1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +struct bitmapped_struct { + unsigned one : 1; + unsigned two : 1; + unsigned three : 1; + unsigned four : 1; + unsigned five : 1; + unsigned six : 1; + unsigned seven : 1; + unsigned eight : 1; +}; + +/* Check that hwasan allows valid bitfield accesses. */ +int __attribute__ ((noinline)) +handle_unaligned_access (struct bitmapped_struct *foo) +{ + if (foo->three) + return foo->four; + + foo->five = 1; + return 1; +} + +int main() +{ + struct bitmapped_struct myvar = {0}; + handle_unaligned_access (&myvar); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/bitfield-2.c b/gcc/testsuite/c-c++-common/hwasan/bitfield-2.c new file mode 100644 index 00000000000..0b3f3aaaf2d --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/bitfield-2.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* Ensure that hwasan instruments bitfield accesses. */ +struct A +{ + /* Ensure the offset from the start of this struct to the bitfield we access + is large enough to be in a different tag. */ + char base[16]; + int : 4; + long x : 7; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 2 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c b/gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c new file mode 100644 index 00000000000..a7a6d91693a --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/builtin-special-handling.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-asan" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ +/* Only skip the -flto tests without the -flto-partition=none. + With -flto-partition=none we still get a asan1 dump file, without that + parameter we only get the lto dump files (which means scan-tree-dump-times + doesn't work. */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "-flto-partition=none" } } */ + +typedef __SIZE_TYPE__ size_t; +/* Functions to observe that HWASAN instruments memory builtins in the expected + manner. */ +void * __attribute__((noinline)) +memset_builtin (void *dest, int value, size_t len) +{ + return __builtin_memset (dest, value, len); +} + +/* HWASAN avoids strlen because it doesn't know the size of the memory access + until *after* the function call. */ +size_t __attribute__ ((noinline)) +strlen_builtin (char *element) +{ + return __builtin_strlen (element); +} + +/* First test ensures that the HWASAN_CHECK was emitted before the + memset. Second test ensures there was only HWASAN_CHECK (which demonstrates + that strlen was not instrumented). */ +/* { dg-final { scan-tree-dump-times "HWASAN_CHECK.*memset" 1 "asan1" } } */ +/* { dg-final { scan-tree-dump-times "HWASAN_CHECK" 1 "asan1" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/check-interface.c b/gcc/testsuite/c-c++-common/hwasan/check-interface.c new file mode 100644 index 00000000000..90f52cac884 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/check-interface.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* + Test taken from LLVM + compiler-rt/test/hwasan/TestCases/check-interface.cpp + */ +// Utilizes all flavors of __hwasan_load/store interface functions to verify +// that the instrumentation and the interface provided by HWASan do match. +// In case of a discrepancy, this test fails to link. + +typedef __UINT8_TYPE__ uint8_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __UINT64_TYPE__ uint64_t; + +#define F(T) void f_##T(T *a, T *b) { *a = *b; } + +F(uint8_t) +F(uint16_t) +F(uint32_t) +F(uint64_t) + +typedef unsigned V32 __attribute__((__vector_size__(32))); +F(V32) + +int main() {} diff --git a/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c new file mode 100644 index 00000000000..90ca856874d --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c @@ -0,0 +1,24 @@ +/* Test recovery mode. */ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-options "-fsanitize-recover=hwaddress" } */ +/* { dg-set-target-env-var HWASAN_OPTIONS "halt_on_error=false" } */ +/* { dg-shouldfail "hwasan" } */ + +volatile int sixteen = 16; + +int main() { + char x[16]; + __builtin_memset(x, 0, sixteen + 1); + asm volatile ("" : : : "memory"); + volatile int res = x[sixteen]; + x[sixteen] = res + 3; + res = x[sixteen]; + return 0; +} + +/* { dg-output "WRITE of size 17 at 0x\[0-9a-f\]+.*" } */ +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */ +/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+.*" } */ +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */ + diff --git a/gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c b/gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c new file mode 100644 index 00000000000..685b7803898 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/handles-poly_int-marked-vars.c @@ -0,0 +1,37 @@ +/* { dg-do compile { target aarch64-*-* } } */ +/* { dg-additional-options "-march=armv8.6-a+sve -fsanitize-address-use-after-scope" } */ + +#include + +__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]; + __SVInt8_t freq; + /* Just do something with that `freq` variable so that the compiler + doesn't optimise its use away. */ + if (__builtin_bcmp (&freq, a, 10)) + j += 1; + __builtin_memset (a, 0, sizeof (a)); + j += foo (a); + } + return j; +} + +/* Just ensure this compiles without giving an ICE. + This is the equivalent of PR 97696 but for HWASAN. HWASAN can handle + poly_int sized variables, and this testcase ensures that we don't ICE when + given them. */ diff --git a/gcc/testsuite/c-c++-common/hwasan/heap-overflow.c b/gcc/testsuite/c-c++-common/hwasan/heap-overflow.c new file mode 100644 index 00000000000..137466800de --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/heap-overflow.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free -fno-builtin-memset" } */ +/* { dg-shouldfail "hwasan" } */ + +#ifdef __cplusplus +extern "C" { +#endif +void *memset (void *, int, __SIZE_TYPE__); +void *malloc (__SIZE_TYPE__); +void free (void *); +#ifdef __cplusplus +} +#endif + +volatile int ten = 10; +int main(int argc, char **argv) { + char *x = (char*)malloc(10); + memset(x, 0, 10); + int res = x[ten]; /* BOOOM */ + free(x); + return res; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "located 0 bytes to the right of 10-byte region.*" } */ +/* { dg-output "allocated here:.*" } */ +/* { dg-output "#1 0x\[0-9a-f\]+ +in _*main \[^\n\r]*heap-overflow.c:18" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c new file mode 100644 index 00000000000..2d6bab4c578 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-poison-optimisation.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ +/* { dg-additional-options "-fdump-tree-asan1 -save-temps" } */ + +/* Here to check that the ASAN_POISON stuff works just fine. + This mechanism isn't very often used, but I should at least go through the + code-path once in my testfile. */ +int +main () +{ + int *ptr = 0; + + { + int a; + ptr = &a; + *ptr = 12345; + } + + return *ptr; +} + +/* { dg-final { scan-tree-dump-times "ASAN_POISON" 1 "asan1" } } */ +/* { dg-final { scan-assembler-times "bl\\s*__hwasan_tag_mismatch4" 1 } } */ +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c new file mode 100644 index 00000000000..828909d3b3b --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-access-parent.c @@ -0,0 +1,51 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "-lpthread" } */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +extern int printf (char const *, ...); +#ifdef __cplusplus +} +#endif +typedef __UINTPTR_TYPE__ uintptr_t; +typedef __UINT64_TYPE__ uint64_t; + +/* Test that tags are checked across different threads. + i.e. if this thread tries to access a different threads memory with the + incorrect tag, then this thread fails. */ +void * +failing_thread_function (void *argument) +{ + void * other = (void *)((uint64_t)argument & 0xffffffffffffffULL); + int *num = (int*)argument; + printf ("(should succeed): first number = %d\n", num[0]); + printf ("(now should fail):\n"); + + int *othernum = (int*)other; + printf (" second number = %d\n", othernum[0]); + return (void *)1; +} + +int +main (int argc, char **argv) +{ + int argument[100] = {0}; + argument[1] = 10; + pthread_t thread_index; + pthread_create (&thread_index, NULL, failing_thread_function, (void*)argument); + + void *retval; + pthread_join (thread_index, &retval); + + return (uintptr_t)retval; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: 00/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T1.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c new file mode 100644 index 00000000000..6a07521e115 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-basic-failure.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "-lpthread" } */ + +/* Ensure the failure mode for hwasan under pthreads looks sane. + (Looks sane means that the same error message is printed out rather than an + opaque message due to mishandling). */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +extern int printf (char const *, ...); +#ifdef __cplusplus +} +#endif +typedef __UINTPTR_TYPE__ uintptr_t; +typedef __UINT64_TYPE__ uint64_t; + +void * +failing_from_stack (void * argument) +{ + int internal_array[16] = {0}; + printf ("(now should fail):"); + printf (" problem number is %d\n", internal_array[17]); + return (void *)1; +} + +int +main (int argc, char **argv) +{ + int argument[100] = {0}; + argument[1] = 10; + pthread_t thread_index; + pthread_create (&thread_index, NULL, failing_from_stack, (void*)argument); + + void *retval; + pthread_join (thread_index, &retval); + + return (uintptr_t)retval; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T1.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T1.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c new file mode 100644 index 00000000000..09c72a56f0f --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-clears-stack.c @@ -0,0 +1,56 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "-lpthread" } */ + +/* This checks the interceptor ABI pthread hooks. + The stack of the thread that is finishing must be cleared of shadow tags + when that thread exits. */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +extern int printf (char const *, ...); +#ifdef __cplusplus +} +#endif +typedef __UINTPTR_TYPE__ uintptr_t; +typedef __UINT64_TYPE__ uint64_t; + +__attribute__ ((noinline)) +void * Ident (void * argument) +{ + return argument; +} + +void * +pthread_stack_is_cleared (void *argument) +{ + (void)argument; + int internal_array[16] = {0}; + return Ident((void*)internal_array); +} + +int +main (int argc, char **argv) +{ + int argument[100] = {0}; + argument[1] = 10; + pthread_t thread_index; + pthread_create (&thread_index, NULL, pthread_stack_is_cleared, (void*)argument); + + void *retval; + pthread_join (thread_index, &retval); + + printf ("(should fail): "); + printf ("value left in stack is: %d\n", ((int *)retval)[0]); + + return (uintptr_t)retval; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "HWAddressSanitizer can not describe address in more detail\..*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c new file mode 100644 index 00000000000..b0281f7b389 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/hwasan-thread-success.c @@ -0,0 +1,35 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-additional-options "-lpthread" } */ + +/* Just ensure that a basic threaded program works while running with hwasan. + */ + +#include + +extern int printf (const char *, ...); +typedef __UINTPTR_TYPE__ uintptr_t; +typedef __UINT64_TYPE__ uint64_t; + +void * +successful_thread_function (void * argument) +{ + int *deref = (int *)argument; + if (deref[0] == 100) + deref[1] = 10; + return (void *)0; +} + +int +main (int argc, char **argv) +{ + int argument[100] = {0}; + argument[1] = 10; + pthread_t thread_index; + pthread_create (&thread_index, NULL, successful_thread_function, (void*)argument); + + void *retval; + pthread_join (thread_index, &retval); + + return (uintptr_t)retval; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c b/gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c new file mode 100644 index 00000000000..abfe735e6e1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/kernel-defaults.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-sanitize=hwaddress -fsanitize=kernel-hwaddress" } */ + + +/* Defaults to check for kernel-hwaddress. + 1) No stack tagging => no calls to __hwasan_tag_memory. + 2) No block scope tagging (same again). + 3) Use sanitize-recover by default (everything ends in noabort). */ +int __attribute__ ((noinline)) +accessing_pointers (int *left, int *right) +{ + int x = right[2]; + left[3] = right[1]; + return right[1] + left[2]; +} + +int __attribute__ ((noinline)) +using_stack (int num) +{ + int big_array[10]; + int other_array[20]; + accessing_pointers(other_array, big_array); + return big_array[num]; +} + +#ifndef ARG +#define ARG 0 +#endif +int __attribute__ ((noinline)) +main () +{ + using_stack (ARG); + return 0; +} + +/* { dg-final { scan-assembler-not "__hwasan_tag_memory" } } */ +/* { dg-final { scan-assembler-not "__hwasan_(load|store)\\d(?!_noabort)" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c new file mode 100644 index 00000000000..5b0071af2be --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-0.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +/* Handling large aligned variables. + Large aligned variables take a different code-path through expand_stack_vars + in cfgexpand.c. This testcase is just to exercise that code-path. + + The alternate code-path produces a second base-pointer through some + instructions emitted in the prologue. + + Test cases are: + 0) Valid access works without complaint. + 1) Invalid access is caught. */ +int __attribute__ ((noinline)) +handle_large_alignment (int num) +{ + int other_array[10]; + int big_array[100] __attribute__ ((aligned (32))); + return big_array[num] + other_array[num]; +} + +#ifndef ARG +#define ARG 1 +#endif + +int global; + +int __attribute__ ((noinline)) +main () +{ + global += handle_large_alignment (ARG); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c new file mode 100644 index 00000000000..1aa13032396 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-1.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +#define ARG 12 +#include "large-aligned-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c new file mode 100644 index 00000000000..11f422fc4fa --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-0.c @@ -0,0 +1,75 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* Don't really need this option since there are no vararray/alloca objects in + the interesting function, however it never hurts to make doubly sure and + make it explicit that we're checking the alternate approach to deallocation. + */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +/* Handling large aligned variables. + Large aligned variables take a different code-path through expand_stack_vars + in cfgexpand.c. This testcase is just to exercise that code-path. + + The alternate code-path produces a second base-pointer through some + instructions emitted in the prologue. + + This eventually follows a different code path for untagging when not tagging + allocas. The untagging needs to work at the top of the frame, and this + should account for this different base when large aligned variables are + around. */ +__attribute__ ((noinline)) +void * Ident (void * argument) +{ + return argument; +} + +#ifndef ALIGNMENT +#define ALIGNMENT +#endif +void __attribute__ ((noinline)) +large_alignment_untagging (int num, int *retval, int **big, int **other) +{ + int other_array[100] ALIGNMENT; + int big_array[100] __attribute__ ((aligned (32))); + *retval = big_array[num] + other_array[num]; + *big = (int*)Ident(big_array); + *other = (int*)Ident(other_array); +} + +#ifndef ARG +#define ARG 0 +#endif + +int global; + +int __attribute__ ((noinline)) +main () +{ + int retval; + int *big, *other; + large_alignment_untagging (0, &retval, &big, &other); + /* Want to test that both ends of both variables are untagged. */ + switch (ARG) { + case 0: + global += big[0]; + break; + case 1: + global += big[99]; + break; + case 2: + global += other[0]; + break; + case 3: + global += other[99]; + break; + } + return 0; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c new file mode 100644 index 00000000000..b2fc522f3c9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-1.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 1 +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c new file mode 100644 index 00000000000..ebc46482fea --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-2.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 2 +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c new file mode 100644 index 00000000000..d3a226a5db0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-3.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 3 +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c new file mode 100644 index 00000000000..cdd122b5f61 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-4.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 0 +#define ALIGNMENT __attribute__ ((aligned (32))) +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c new file mode 100644 index 00000000000..7c4cb5cb218 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-5.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 1 +#define ALIGNMENT __attribute__ ((aligned (32))) +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c new file mode 100644 index 00000000000..f429ed21106 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-6.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 2 +#define ALIGNMENT __attribute__ ((aligned (32))) +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c new file mode 100644 index 00000000000..56f16eb169d --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/large-aligned-untagging-7.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0" } */ + +#define ARG 3 +#define ALIGNMENT __attribute__ ((aligned (32))) +#include "large-aligned-untagging-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* NOTE: This assumes the current tagging mechanism (one at a time from the + base and large aligned variables being handled first). */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/macro-definition.c b/gcc/testsuite/c-c++-common/hwasan/macro-definition.c new file mode 100644 index 00000000000..5f654f55782 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/macro-definition.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +extern void testfunc(int); +int foo() +{ +#ifndef __SANITIZE_HWADDRESS__ + testfunc(1); +#endif + return 1; +} + +/* { dg-final { scan-assembler-not "testfunc" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c b/gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c new file mode 100644 index 00000000000..c0a254dc83a --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/no-sanitize-attribute.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +__attribute__((no_sanitize("hwaddress"))) int +f (int *p, int *q) +{ + *p = 42; + return *q; +} + +/* Only have one instance of __hwasan, it is __hwasan_init (the module + * constructor) there is no instrumentation in the function. */ +/* { dg-final { scan-assembler-times "__hwasan" 1 } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c new file mode 100644 index 00000000000..f1e6dc8a8d3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-mem-intrinsics.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ +/* { dg-additional-options "--param hwasan-instrument-mem-intrinsics=0" } */ + +#include "builtin-special-handling.c" + +/* With this flag there should be no checking of builtins. + The above file only has builtins, and hence there should be no checking + after compilation. */ +/* { dg-final { scan-assembler-not "__hwasan_(load|store)" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c new file mode 100644 index 00000000000..1d565a2f5d9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads-and-writes.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param hwasan-instrument-writes=0" } */ + +#include "param-instrument-reads.c" + +/* { dg-final { scan-assembler "__hwasan_load" } } */ +/* { dg-final { scan-assembler-not "__hwasan_store" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c new file mode 100644 index 00000000000..9b8049a3cb9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-reads.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param hwasan-instrument-reads=0" } */ + +typedef __SIZE_TYPE__ size_t; +/* Particular code doesn't really matter, the requirement is that it has both + loads and stores in it. */ +__attribute__ ((noinline)) +int reader (int *array, size_t num) +{ + return array[num]; +} + +int __attribute__ ((noinline)) +writer (int *array, size_t num, int value) +{ + array[num] = value; + return num + value; +} + +/* { dg-final { scan-assembler-not "__hwasan_load" } } */ +/* { dg-final { scan-assembler "__hwasan_store" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c b/gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c new file mode 100644 index 00000000000..0f04fad6496 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/param-instrument-writes.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param hwasan-instrument-reads=0 --param hwasan-instrument-writes=0" } */ + +#include "param-instrument-reads.c" + +/* { dg-final { scan-assembler-not "__hwasan_load" } } */ +/* { dg-final { scan-assembler-not "__hwasan_store" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c b/gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c new file mode 100644 index 00000000000..8e55b298470 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/random-frame-tag.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param hwasan-random-frame-tag=1" } */ + +#include "stack-tagging-basic-0.c" + +/* Random frame tag => call to __hwasan_generate_tag. */ +/* { dg-final { scan-assembler "__hwasan_generate_tag" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c b/gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c new file mode 100644 index 00000000000..a42921bb44c --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/sanity-check-pure-c.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-shouldfail "asan" } */ + +#ifdef __cplusplus +extern "C" { +#endif +void *malloc (__SIZE_TYPE__); +void free (void *); +#ifdef __cplusplus +} +#endif + +int main() { + char *x = (char*)malloc(10); + free(x); + return x[5]; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "located 5 bytes inside of 10-byte region.*" } */ +/* { dg-output "freed by thread T0 here:.*" } */ +/* { dg-output "previously allocated here:" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c new file mode 100644 index 00000000000..019c4ea3f74 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-0.c @@ -0,0 +1,54 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +#include +#include + +/* + Testing longjmp/setjmp should test. + + 0) Nothing special happens with the jmp_buf. + 1) Accesses to scopes jmp'd over are caught. + */ +int __attribute__ ((noinline)) +uses_longjmp (int **other_array, int num, jmp_buf env) +{ + int internal_array[100] = {0}; + *other_array = &internal_array[0]; + if (num % 2) + longjmp (env, num); + else + return num % 8; +} + +int __attribute__ ((noinline)) +uses_setjmp (int num) +{ + int big_array[100]; + int *other_array = NULL; + sigjmp_buf cur_env; + int temp = 0; + if ((temp = sigsetjmp (cur_env, 1)) != 0) + { + if (other_array != NULL) + printf ("Value pointed to in other_array[0]: %d\n", + other_array[0]); + + printf ("Longjmp returned %d.\n", temp); + return 10; + } + else + { + return uses_longjmp (&other_array, num, cur_env); + } +} + +#ifndef ARG +#define ARG 0 +#endif +int __attribute__ ((noinline)) +main () +{ + uses_setjmp (ARG); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c new file mode 100644 index 00000000000..6a4fceeb37a --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/setjmp-longjmp-1.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* + Testing longjmp/setjmp should test. + + 0) Nothing special happens with the jmp_buf. + 1) Accesses to scopes jmp'd over are caught. + */ + +#define ARG 1 +#include "setjmp-longjmp-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c new file mode 100644 index 00000000000..114114165d9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-0.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +/* Basic tests for stack tagging. + + 0) Valid accesses work. + 1) Accesses outside of a variable crash. +*/ +int __attribute__ ((noinline)) +accessing_pointers (int *left, int *right) +{ + int x = right[2]; + left[3] = right[1]; + return right[1] + left[2]; +} + +int __attribute__ ((noinline)) +using_stack (int num) +{ + int big_array[10]; + int other_array[20]; + accessing_pointers(other_array, big_array); + return big_array[num]; +} + +#ifndef ARG +#define ARG 0 +#endif + +int global; + +int __attribute__ ((noinline)) +main () +{ + global += using_stack (ARG); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c new file mode 100644 index 00000000000..90d5837254f --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-basic-1.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* Basic tests for stack tagging. + + 0) Accesses outside of a variable crash. + 1) Valid accesses work. +*/ + +#define ARG 17 +#include "stack-tagging-basic-0.c" +#undef ARG + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c new file mode 100644 index 00000000000..9bcae162500 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/stack-tagging-disable.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param hwasan-instrument-stack=0" } */ + + +/* No stack tagging => no calls to __hwasan_tag_memory. */ +int __attribute__ ((noinline)) +accessing_pointers (int *left, int *right) +{ + int x = right[2]; + left[3] = right[1]; + return right[1] + left[2]; +} + +int __attribute__ ((noinline)) +using_stack (int num) +{ + int big_array[10]; + int other_array[20]; + accessing_pointers(other_array, big_array); + return big_array[num]; +} + +#ifndef ARG +#define ARG 0 +#endif +int __attribute__ ((noinline)) +main () +{ + using_stack (ARG); + return 0; +} + +/* { dg-final { scan-assembler-not "__hwasan_tag_memory" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c new file mode 100644 index 00000000000..88465155c6d --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-0.c @@ -0,0 +1,46 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0 -save-temps" } */ +/* Only run this test without optimisation. When running with optimisation we + use the unprotected-allocas-1.c file that also checks there are no memory + tagging calls (since when optimised the only variable on the stack should be + the vararray/alloca). */ +/* { dg-skip-if "" { *-*-* } { "-O1" "-O2" "-O3" } { "" } } */ + +#define alloca __builtin_alloca +#define assert(x) if (!(x)) __builtin_abort () + +char tag_of (void * x) { return ((unsigned long long)x) >> 56; } + +int __attribute__ ((noinline)) +using_alloca (int num) +{ + int retval = 0; + int *big_array = (int*)alloca (num * sizeof (int)); + char alloca_tag = tag_of (big_array); + assert (alloca_tag == 0); + for (int i = 0; i < num; ++i) { + retval += big_array[i]; + } + return retval; +} + +int __attribute__ ((noinline)) +using_vararray (int num) +{ + int retval = 0; + int big_array[num]; + char vararray_tag = tag_of (big_array); + assert (vararray_tag == 0); + for (int i = 0; i < num; ++i) { + retval += big_array[i]; + } + return retval; +} + +int main() +{ + using_alloca (16); + using_vararray (12); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c new file mode 100644 index 00000000000..752edc1d3ea --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/unprotected-allocas-1.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-additional-options "--param hwasan-instrument-allocas=0 -save-temps" } */ +/* Only test there's no tagging done when not at -O0. Without optimisation + the compiler creates a bunch of other variables on the stack other than the + vararray/alloca object. + We also avoid checking when using -flto, since with LTO the compiler can + recognise the vararray is only used with one size and that size is known at + compile time -- when the compiler recognises that it instead creates a + static array, which gets tagged as is expected but not as the test expects. + */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-flto" } { "" } } */ + +#include "unprotected-allocas-0.c" + +/* { dg-final { scan-assembler-not "__hwasan_tag_memory" } } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/use-after-free.c b/gcc/testsuite/c-c++-common/hwasan/use-after-free.c new file mode 100644 index 00000000000..41a356999aa --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/use-after-free.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-shouldfail "hwasan" } */ + +#ifdef __cplusplus +extern "C" { +#endif +void *malloc (__SIZE_TYPE__); +void free (void *); +#ifdef __cplusplus +} +#endif + +int main() { + char *x = (char*)malloc(10); + free(x); + return x[5]; +} + + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/\[\[:xdigit:\]\]\[\[:xdigit:\]\] \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "is located 5 bytes inside of 10-byte region.*" } */ +/* { dg-output "freed by thread T0 here:.*" } */ +/* { dg-output "#1\[^\n\r]*main\[^\n\r]*use-after-free.c:17.*" } */ +/* { dg-output "previously allocated here:.*" } */ +/* { dg-output "#1\[^\n\r]*main\[^\n\r]*use-after-free.c:16" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c b/gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c new file mode 100644 index 00000000000..35a344def42 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/vararray-outside-caught.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +int __attribute__ ((noinline)) +check_vararray (int num) +{ + int var_array[num]; + int other_array[10]; + return var_array[12]; +} + +int __attribute__ ((noinline)) +main () +{ + return check_vararray (3); +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "READ of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c b/gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c new file mode 100644 index 00000000000..f4e1f57bdd2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/vararray-stack-restore-correct.c @@ -0,0 +1,43 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +#include + +/* Testing that a function with outgoing arguments correctly decrements the + stack pointer when a vararray goes out of scope. */ + +const char * +other (int argc, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) +{ + const char ** other; + { + const char * test_array[argc]; + test_array[0] = "test string"; + test_array[argc - 1] = "hello"; + /* To prevent optimisation. */ + printf("While the value stored in our test_array is: %s\n", + test_array[argc - 1]); + other = test_array; + } + /* With the below function call (the one with many arguments), some of the + arguments have to be put on the stack, which means we have to reserve some + space on the stack for these arguments and that the VLA is stored at a + position that is not the stack pointer. */ + printf("Hello there!\nOur numbers today are: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", + a, b, c, d, e, f, g, h, i, j, k, l); + /* This should fail due to a bad read access. */ + return other[0]; +} + +int +main () +{ + int a, b, c, d, e, f, g, h, i, j, k, l; + const char * retval = other (1, a, b, c, d, e, f, g, h, i, j, k, l); + /* Numbers don't matter here, just want to ensure the program is reading them + so we know they won't be optimised out. */ + if (retval) + return 1; + return 10; +} diff --git a/gcc/testsuite/c-c++-common/hwasan/very-large-objects.c b/gcc/testsuite/c-c++-common/hwasan/very-large-objects.c new file mode 100644 index 00000000000..55265353369 --- /dev/null +++ b/gcc/testsuite/c-c++-common/hwasan/very-large-objects.c @@ -0,0 +1,68 @@ +/* { dg-do compile } */ + +/* Ensure the sanitizer can handle very large offsets (i.e. that the hooks + handle offsets too large for the relevant instructions). + Just want to make sure this compiles without an ICE. */ +#ifndef ASIZE +# define ASIZE 0x10000000000UL +#endif + +typedef __UINT64_TYPE__ uint64_t; + +#if __LONG_MAX__ < 8 * ASIZE +# undef ASIZE +# define ASIZE 4096 +#endif + +extern void abort (void); + +int __attribute__((noinline)) +foo (const char *s) +{ + if (!s) + return 1; + if (s[0] != 'a') + abort (); + s += ASIZE - 1; + if (s[0] != 'b') + abort (); + return 0; +} + +int (*fn) (const char *) = foo; + +int __attribute__((noinline)) +bar (void) +{ + char s[ASIZE]; + s[0] = 'a'; + s[ASIZE - 1] = 'b'; + foo (s); + foo (s); + return 0; +} + +int __attribute__((noinline)) +baz (long i) +{ + if (i) + return fn (0); + else + { + char s[ASIZE]; + s[0] = 'a'; + s[ASIZE - 1] = 'b'; + foo (s); + foo (s); + return fn (0); + } +} + +int __attribute__((noinline)) +very_large_offset (int *p) +{ + char init_array[(uint64_t)0xfefefef]; + char other_array[(uint64_t)0xfefefef]; + return (int)init_array[p[1]] + (int)other_array[p[0]]; +} + diff --git a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c index f325a747228..55db0c0b865 100644 --- a/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c +++ b/gcc/testsuite/c-c++-common/ubsan/sanitize-recover-7.c @@ -3,4 +3,4 @@ int i; -/* { dg-error ".-fsanitize=thread. is incompatible with .-fsanitize=address|kernel-address." "" { target *-*-* } 0 } */ +/* { dg-error ".-fsanitize=thread. is incompatible with .-fsanitize=address." "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/g++.dg/hwasan/hwasan.exp b/gcc/testsuite/g++.dg/hwasan/hwasan.exp new file mode 100644 index 00000000000..559cf066f18 --- /dev/null +++ b/gcc/testsuite/g++.dg/hwasan/hwasan.exp @@ -0,0 +1,34 @@ +# Copyright (C) 2012-2019 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Load support procs. +load_lib g++-dg.exp +load_lib hwasan-dg.exp + +# Initialize `dg'. +dg-init +hwasan_init + +# Main loop. +if [check_effective_target_fsanitize_hwaddress] { + gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/hwasan/*.c]] "" "" +} + +# All done. +hwasan_finish +dg-finish diff --git a/gcc/testsuite/g++.dg/hwasan/rvo-handled.C b/gcc/testsuite/g++.dg/hwasan/rvo-handled.C new file mode 100644 index 00000000000..0e30ff054fc --- /dev/null +++ b/gcc/testsuite/g++.dg/hwasan/rvo-handled.C @@ -0,0 +1,46 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +#define assert(x) if (!(x)) __builtin_abort () +typedef __UINTPTR_TYPE__ uintptr_t; +void *untagged (void *ptr) +{ + /* Untag by removing the top byte. */ + return (void*)((uintptr_t)ptr & 0xffffffffffffff); +} + +struct big_struct { + int left; + int right; + void *ptr; + int big_array[100]; +}; + +/* + Tests for RVO (basically, checking -fsanitize=hwaddress has not broken RVO + in any way). + + 0) The value is accessible in both functions without a hwasan complaint. + 1) RVO does happen. + */ + +struct big_struct __attribute__ ((noinline)) +return_on_stack() +{ + struct big_struct x; + x.left = 100; + x.right = 20; + x.big_array[10] = 30; + x.ptr = untagged(&x); + return x; +} + +int main() +{ + struct big_struct x; + x = return_on_stack(); + /* Check that RVO happens by checking the address that the callee saw. */ + assert (x.ptr == untagged(&x)); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/hwasan/hwasan.exp b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp new file mode 100644 index 00000000000..5c040aec24a --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp @@ -0,0 +1,36 @@ +# Copyright (C) 2012-2019 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp +load_lib hwasan-dg.exp + +# Initialize `dg'. +dg-init +hwasan_init + +# Main loop. +if [check_effective_target_fsanitize_hwaddress] { + gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/hwasan/*.c]] "" "" +} + +# All done. +hwasan_finish +dg-finish diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c new file mode 100644 index 00000000000..0afcc100508 --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-0.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ + +/* + Tests of nested funtions are: + 0) Accessing closed over variables works. + 1) Accesses outside of variables is caught. + 2) Accessing variable out of scope is caught. + + Here we test that accessing closed over variables works. + */ + +/* We need a second layer of indirection so that GCC doesn't notice we're + returning the address of a local variable and put 0 in it's place. */ +__attribute__((noinline)) +int *Ident(void *x) { + return x; +} + +int __attribute__ ((noinline)) +intermediate (void (*f) (int, char), + char num) +{ + if (num == 1) + /* NOTE: We need to overrun by an amount greater than the "extra data" in a + nonlocal goto structure. The entire structure is allocated on the stack + with a single tag, which means hwasan can't tell if a closed-over buffer + was overrun by an amount small enough that the access was still to some + data in that nonlocal goto structure. */ + f (100, 100); + else + f (3, 100); + /* Just return something ... */ + return num % 3; +} + +int* __attribute__ ((noinline)) +nested_function (char num) +{ + int big_array[16]; + int other_array[16]; + void store (int index, char value) + { big_array[index] = value; } + return Ident(&other_array[intermediate (store, num)]); +} + +#ifndef MAIN +int main () +{ + nested_function (0); + return 0; +} +#endif diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c new file mode 100644 index 00000000000..016128101e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-1.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* + Tests of nested funtions are: + 0) Accessing closed over variables works. + 1) Accesses outside of variables is caught. + 2) Accessing variable out of scope is caught. + + Here we test option 1. + */ + +#define MAIN 0 +#include "nested-functions-0.c" +#undef MAIN + +int main () +{ + nested_function (1); + return 0; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c b/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c new file mode 100644 index 00000000000..b1a033fdb36 --- /dev/null +++ b/gcc/testsuite/gcc.dg/hwasan/nested-functions-2.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-require-effective-target hwaddress_exec } */ +/* { dg-shouldfail "hwasan" } */ + +/* + Tests of nested funtions are: + 0) Accessing closed over variables works. + 1) Accesses outside of variables is caught. + 2) Accessing variable out of scope is caught. + + Here we test option 2. + */ + +#define MAIN 0 +#include "nested-functions-0.c" +#undef MAIN + +int main () +{ + int *retval = nested_function (2); + *retval = 100; + return 0; +} + +/* { dg-output "HWAddressSanitizer: tag-mismatch on address 0x\[0-9a-f\]*.*" } */ +/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]* tags: \[\[:xdigit:\]\]\[\[:xdigit:\]\]/00 \\(ptr/mem\\) in thread T0.*" } */ +/* { dg-output "Address 0x\[0-9a-f\]* is located in stack of thread T0.*" } */ +/* { dg-output "SUMMARY: HWAddressSanitizer: tag-mismatch \[^\n\]*.*" } */ diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index ce745dfdf8d..8f96751bfac 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -16,6 +16,9 @@ # Return 1 if compilation with -fsanitize=address is error-free for trivial # code, 0 otherwise. +# +# NOTE: This should only be used between calls to asan_init and asan_finish. +# It is therefore defined here rather than in target-supports.exp. proc check_effective_target_fsanitize_address {} { if ![check_no_compiler_messages fsanitize_address executable { @@ -58,33 +61,33 @@ proc asan_include_flags {} { # (originally from g++.exp) # -proc asan_link_flags { paths } { +proc asan_link_flags_1 { paths lib } { global srcdir global ld_library_path global shlib_ext - global asan_saved_library_path + global ${lib}_saved_library_path set gccpath ${paths} set flags "" set shlib_ext [get_shlib_extension] - set asan_saved_library_path $ld_library_path + set ${lib}_saved_library_path $ld_library_path if { $gccpath != "" } { - if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"] - || [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.${shlib_ext}"] } { + if { [file exists "${gccpath}/libsanitizer/${lib}/.libs/lib${lib}.a"] + || [file exists "${gccpath}/libsanitizer/${lib}/.libs/lib${lib}.${shlib_ext}"] } { append flags " -B${gccpath}/libsanitizer/ " - append flags " -B${gccpath}/libsanitizer/asan/ " - append flags " -L${gccpath}/libsanitizer/asan/.libs " - append ld_library_path ":${gccpath}/libsanitizer/asan/.libs" + append flags " -B${gccpath}/libsanitizer/${lib}/ " + append flags " -L${gccpath}/libsanitizer/${lib}/.libs " + append ld_library_path ":${gccpath}/libsanitizer/${lib}/.libs" } } else { global tool_root_dir - set libasan [lookfor_file ${tool_root_dir} libasan] - if { $libasan != "" } { - append flags "-L${libasan} " - append ld_library_path ":${libasan}" + set libdir [lookfor_file ${tool_root_dir} lib${lib}] + if { $libdir != "" } { + append flags "-L${libdir} " + append ld_library_path ":${libdir}" } } @@ -93,6 +96,10 @@ proc asan_link_flags { paths } { return "$flags" } +proc asan_link_flags { paths } { + return [asan_link_flags_1 $paths asan] +} + # # asan_init -- called at the start of each subdir of tests # diff --git a/gcc/testsuite/lib/hwasan-dg.exp b/gcc/testsuite/lib/hwasan-dg.exp new file mode 100644 index 00000000000..892f2bab433 --- /dev/null +++ b/gcc/testsuite/lib/hwasan-dg.exp @@ -0,0 +1,150 @@ +# Copyright (C) 2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +load_lib asan-dg.exp + +# Return 1 if target can compile a binary for hardware address +# sanitization, 0 otherwise. +# +# NOTE: This should only be used between calls to hwasan_init and +# hwasan_finish. It is therefore defined here rather than in +# target-supports.exp. + +proc check_effective_target_fsanitize_hwaddress {} { + if ![check_no_compiler_messages fsanitize_hwaddress executable { + int main (void) { return 0; } + }] { + return 0; + } + return 1; +} + +# Return 1 if target can compile and run a binary for hardware address +# sanitization, 0 otherwise. +# +# NOTE: This should only be used between calls to hwasan_init and +# hwasan_finish. It is therefore defined here rather than in +# target-supports.exp. + +proc check_effective_target_hwaddress_exec {} { + if ![check_runtime hwaddress_exec { + int main (void) { return 0; } + }] { + return 0; + } + return 1; +} + +proc hwasan_include_flags {} { + global srcdir + global TESTING_IN_BUILD_TREE + + set flags "" + + if { [is_remote host] || ! [info exists TESTING_IN_BUILD_TREE] } { + return "${flags}" + } + + set flags "-I$srcdir/../../libsanitizer/include" + + return "$flags" +} + +# +# hwasan_link_flags -- compute library path and flags to find libhwasan. +# (implementation in asan-dg.exp) +# + +proc hwasan_link_flags { paths } { + return [asan_link_flags_1 $paths hwasan] +} + +# +# hwasan_init -- called at the start of each subdir of tests +# + +proc hwasan_init { args } { + global TEST_ALWAYS_FLAGS + global ALWAYS_CXXFLAGS + global TOOL_OPTIONS + global hwasan_saved_TEST_ALWAYS_FLAGS + global hwasan_saved_ALWAYS_CXXFLAGS + + setenv HWASAN_OPTIONS "random_tags=0" + + set link_flags "" + if ![is_remote host] { + if [info exists TOOL_OPTIONS] { + set link_flags "[hwasan_link_flags [get_multilibs ${TOOL_OPTIONS}]]" + } else { + set link_flags "[hwasan_link_flags [get_multilibs]]" + } + } + + set include_flags "[hwasan_include_flags]" + + if [info exists TEST_ALWAYS_FLAGS] { + set hwasan_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS + } + if [info exists ALWAYS_CXXFLAGS] { + set hwasan_saved_ALWAYS_CXXFLAGS $ALWAYS_CXXFLAGS + set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS] + set ALWAYS_CXXFLAGS [concat "{additional_flags=-fsanitize=hwaddress --param hwasan-random-frame-tag=0 -g $include_flags}" $ALWAYS_CXXFLAGS] + } else { + if [info exists TEST_ALWAYS_FLAGS] { + set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=hwaddress --param hwasan-random-frame-tag=0 -g $include_flags $TEST_ALWAYS_FLAGS" + } else { + set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=hwaddress --param hwasan-random-frame-tag=0 -g $include_flags" + } + } +} + +# +# hwasan_finish -- called at the start of each subdir of tests +# + +proc hwasan_finish { args } { + global TEST_ALWAYS_FLAGS + global hwasan_saved_TEST_ALWAYS_FLAGS + global hwasan_saved_ALWAYS_CXXFLAGS + global hwasan_saved_library_path + global ld_library_path + + unsetenv HWASAN_OPTIONS + + if [info exists hwasan_saved_ALWAYS_CXXFLAGS ] { + set ALWAYS_CXXFLAGS $hwasan_saved_ALWAYS_CXXFLAGS + } else { + if [info exists hwasan_saved_TEST_ALWAYS_FLAGS] { + set TEST_ALWAYS_FLAGS $hwasan_saved_TEST_ALWAYS_FLAGS + } else { + unset TEST_ALWAYS_FLAGS + } + } + if [info exists hwasan_saved_library_path] { + set ld_library_path $hwasan_saved_library_path + set_ld_library_path_env_vars + } + clear_effective_target_cache +} + +# Utility for running gtest hwasan emulation under dejagnu, invoked via dg-final. +# Call pass if variable has the desired value, otherwise fail. +# +# Argument 0 handles expected failures and the like +proc hwasan-gtest { args } { + asan-gtest {*}$args +} -- 2.30.2