diff options
Diffstat (limited to 'gcc/testsuite/c-c++-common/asan')
51 files changed, 1204 insertions, 0 deletions
diff --git a/gcc/testsuite/c-c++-common/asan/asan-interface-1.c b/gcc/testsuite/c-c++-common/asan/asan-interface-1.c new file mode 100644 index 0000000000..8cd80caaa3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/asan-interface-1.c @@ -0,0 +1,14 @@ +/* Check that interface headers work. */ + +/* { dg-do run { target { *-*-linux* } } } */ + +#include <stdbool.h> +#include <sanitizer/asan_interface.h> + +int main() { + char tmp; + if (__asan_address_is_poisoned((volatile char *)&tmp + 1)) + return 0; + return 1; +} + diff --git a/gcc/testsuite/c-c++-common/asan/attrib-1.c b/gcc/testsuite/c-c++-common/asan/attrib-1.c new file mode 100644 index 0000000000..a2a7f7c9f9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/attrib-1.c @@ -0,0 +1,62 @@ +/* PR sanitizer/55435 */ +/* { dg-do compile } */ + +__attribute__((no_sanitize_address)) int +f1 (int *p, int *q) +{ + *p = 42; + return *q; +} + +void f2 (char *); +void f2 (char *) __attribute__((no_sanitize_address)); +void f2 (char *) __attribute__((no_sanitize_address)); +void f2 (char *); + +void +f2 (char *p) +{ + *p = 42; +} + +void f3 (short *); +__typeof (f3) f3 __attribute__((__no_sanitize_address__)); + +void +f3 (short *p) +{ + *p = 42; +} + +__attribute__((no_sanitize_address)) int +f4 (int *p, int *q) +{ + *p = 42; + return *q; +} + +void f5 (char *); +void f5 (char *) __attribute__((no_sanitize_address)); +void f5 (char *) __attribute__((no_sanitize_address)); +void f5 (char *); + +void +f5 (char *p) +{ + *p = 42; +} + +void f6 (short *); +__typeof (f6) f6 __attribute__((__no_address_safety_analysis__)); + +void +f6 (short *p) +{ + *p = 42; +} + +int v __attribute__((no_sanitize_address)); /* { dg-warning "attribute ignored" } */ +int v2 __attribute__((no_address_safety_analysis)); /* { dg-warning "attribute ignored" } */ + +/* { dg-final { scan-assembler-not "__asan_report_store" } } */ +/* { dg-final { scan-assembler-not "__asan_report_load" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/bitfield-1.c b/gcc/testsuite/c-c++-common/asan/bitfield-1.c new file mode 100644 index 0000000000..b3f300c648 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/bitfield-1.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with non-round size. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + 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 "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc/testsuite/c-c++-common/asan/bitfield-2.c b/gcc/testsuite/c-c++-common/asan/bitfield-2.c new file mode 100644 index 0000000000..8ab0f8069f --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/bitfield-2.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with non-round offset. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 7; + int x : 8; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc/testsuite/c-c++-common/asan/bitfield-3.c b/gcc/testsuite/c-c++-common/asan/bitfield-3.c new file mode 100644 index 0000000000..c5907786f7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/bitfield-3.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with round offset. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 8; + int x : 8; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc/testsuite/c-c++-common/asan/bitfield-4.c b/gcc/testsuite/c-c++-common/asan/bitfield-4.c new file mode 100644 index 0000000000..94de9a4376 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/bitfield-4.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with round offset. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 0; + int x : 8; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc/testsuite/c-c++-common/asan/clone-test-1.c b/gcc/testsuite/c-c++-common/asan/clone-test-1.c new file mode 100644 index 0000000000..fd187aaadd --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/clone-test-1.c @@ -0,0 +1,46 @@ +/* Regression test for: + http://code.google.com/p/address-sanitizer/issues/detail?id=37 */ + +/* { dg-do run { target { *-*-linux* } } } */ +/* { dg-require-effective-target clone } */ +/* { dg-require-effective-target hw } */ +/* { dg-options "-D_GNU_SOURCE" } */ + +#include <stdio.h> +#include <stdlib.h> +#include <sched.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +int Child(void *arg) { + char x[32] = {0}; /* Stack gets poisoned. */ + printf("Child: %p\n", x); + _exit(1); /* NoReturn, stack will remain unpoisoned unless we do something. */ +} + +volatile int zero = 0; + +int main(int argc, char **argv) { + int i; + const int kStackSize = 1 << 20; + char child_stack[kStackSize + 1]; + char *sp = child_stack + kStackSize; /* Stack grows down. */ + printf("Parent: %p\n", sp); + pid_t clone_pid = clone(Child, sp, CLONE_FILES | CLONE_VM, NULL, 0, 0, 0); + int status; + pid_t wait_result = waitpid(clone_pid, &status, __WCLONE); + if (wait_result < 0) { + perror("waitpid"); + return 1; + } + if (wait_result == clone_pid && WIFEXITED(status)) { + /* Make sure the child stack was indeed unpoisoned. */ + for (i = 0; i < kStackSize; i++) + child_stack[i] = i; + int ret = child_stack[zero]; + return ret; + } + return 1; +} diff --git a/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c b/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c new file mode 100644 index 0000000000..0576155c28 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c @@ -0,0 +1,16 @@ +/* This test checks that we are no instrumenting a memory access twice + (before and after inlining) */ + +/* { dg-do compile } */ +/* { dg-final { scan-assembler-not "__asan_report_load" } } */ + +__attribute__((always_inline)) +inline void foo(int *x) { + *x = 0; +} + +int main() { + int x; + foo(&x); + return x; +} diff --git a/gcc/testsuite/c-c++-common/asan/global-overflow-1.c b/gcc/testsuite/c-c++-common/asan/global-overflow-1.c new file mode 100644 index 0000000000..66e91479cf --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/global-overflow-1.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-memset" } */ +/* { dg-shouldfail "asan" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void *memset (void *, int, __SIZE_TYPE__); + +volatile int ten = 10; + +int main() { + static char XXX[10]; + static char YYY[10]; + static char ZZZ[10]; + memset(XXX, 0, 10); + memset(YYY, 0, 10); + memset(ZZZ, 0, 10); + int res = YYY[ten]; /* BOOOM */ + res += XXX[ten/10] + ZZZ[ten/10]; + return res; +} + +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */ +/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */ +/* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c b/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c new file mode 100644 index 0000000000..996909d3c8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free -fno-builtin-memset" } */ +/* { dg-shouldfail "asan" } */ + +#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 "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/inc.c b/gcc/testsuite/c-c++-common/asan/inc.c new file mode 100644 index 0000000000..36cc3d8d81 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/inc.c @@ -0,0 +1,21 @@ +/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +void +foo(int *a) +{ + (*a)++; +} + +int +main () +{ + int a = 0; + foo (&a); + return 0; +} + +/* { dg-final { scan-tree-dump-times "ASAN_" 1 "asan0" } } */ +/* { dg-final { scan-tree-dump "ASAN_CHECK \\(.*, 4\\);" "asan0" } } */ +/* { dg-final { cleanup-tree-dump "asan0" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c b/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c new file mode 100644 index 0000000000..32e32a600c --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c @@ -0,0 +1,10 @@ +/* { dg-do assemble } */ +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=0 -save-temps" } */ + +void f(char *a, int *b) { + *b = *a; +} + +/* { dg-final { scan-assembler "__asan_load1" } } */ +/* { dg-final { scan-assembler "__asan_store4" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c b/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c new file mode 100644 index 0000000000..1b361e6270 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=1 -save-temps" } */ + +int x; + +void f(int *a, int *b) { + *a = 0; + asm volatile ("" ::: "memory"); + x = *b; +} + +/* { dg-final { scan-assembler "__asan_store4" } } */ +/* { dg-final { scan-assembler-not "__asan_report_store4" } } */ +/* { dg-final { scan-assembler "__asan_load4" } } */ +/* { dg-final { scan-assembler-not "__asan_report_load4" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/memcmp-1.c b/gcc/testsuite/c-c++-common/asan/memcmp-1.c new file mode 100644 index 0000000000..03f32e92a3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/memcmp-1.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-memcmp" } */ +/* { dg-shouldfail "asan" } */ + +#include <string.h> + +volatile int one = 1; + +int +main () +{ + char a1[] = {one, 2, 3, 4}; + char a2[] = {1, 2*one, 3, 4}; + int res = memcmp (a1, a2, 5 + one); + return res; +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)memcmp |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/memcmp-2.c b/gcc/testsuite/c-c++-common/asan/memcmp-2.c new file mode 100644 index 0000000000..be20cd81ee --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/memcmp-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +int +foo () +{ + char s0[5] = {0}; + char s1[5] = {1}; + + return __builtin_memcmp (s0, s1, 2); +} diff --git a/gcc/testsuite/c-c++-common/asan/misalign-1.c b/gcc/testsuite/c-c++-common/asan/misalign-1.c new file mode 100644 index 0000000000..0c5b6e0c75 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/misalign-1.c @@ -0,0 +1,42 @@ +/* { dg-do run { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2" } */ +/* { dg-shouldfail "asan" } */ + +struct S { int i; } __attribute__ ((packed)); + +__attribute__((noinline, noclone)) int +foo (struct S *s) +{ + return s->i; +} + +__attribute__((noinline, noclone)) int +bar (int *s) +{ + return *s; +} + +__attribute__((noinline, noclone)) struct S +baz (struct S *s) +{ + return *s; +} + +int +main () +{ + struct T { char a[3]; struct S b[3]; char c; } t; + int v = 5; + struct S *p = t.b; + asm volatile ("" : "+rm" (p)); + p += 3; + if (bar (&v) != 5) __builtin_abort (); + volatile int w = foo (p); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ +/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*foo(\[^\n\r]*misalign-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/misalign-2.c b/gcc/testsuite/c-c++-common/asan/misalign-2.c new file mode 100644 index 0000000000..7fbe299cc5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/misalign-2.c @@ -0,0 +1,42 @@ +/* { dg-do run { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2" } */ +/* { dg-shouldfail "asan" } */ + +struct S { int i; } __attribute__ ((packed)); + +__attribute__((noinline, noclone)) int +foo (struct S *s) +{ + return s->i; +} + +__attribute__((noinline, noclone)) int +bar (int *s) +{ + return *s; +} + +__attribute__((noinline, noclone)) struct S +baz (struct S *s) +{ + return *s; +} + +int +main () +{ + struct T { char a[3]; struct S b[3]; char c; } t; + int v = 5; + struct S *p = t.b; + asm volatile ("" : "+rm" (p)); + p += 3; + if (bar (&v) != 5) __builtin_abort (); + volatile struct S w = baz (p); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ +/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*baz(\[^\n\r]*misalign-2.c:22|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-asan-globals.c b/gcc/testsuite/c-c++-common/asan/no-asan-globals.c new file mode 100644 index 0000000000..70a1f95a3a --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-asan-globals.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-save-temps --param asan-globals=0" } */ + +volatile int ten = 10; + +int main() { + volatile static char XXX[10]; + XXX[ten]; + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_register_globals" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-asan-stack.c b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c new file mode 100644 index 0000000000..0f65ab3f7a --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */ +/* { dg-options "--param asan-stack=0" } */ +#include <string.h> + +volatile int one = 1; + +int +main () +{ + volatile char a1[] = {one, 2, 3, 4}; + volatile char a2[] = {1, 2*one, 3, 4}; + volatile int res = memcmp ((void *)a1,(void *)a2, 5 + one); + return 0; +} + +/* { dg-final { scan-assembler-not "0x41b58ab3|0x41B58AB3|1102416563" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c b/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c new file mode 100644 index 0000000000..df75878de2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "--param asan-instrument-reads=0 -save-temps" } */ + +volatile int ten = 10; + +int main() { + volatile char x[10]; + x[ten]; + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_load" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c b/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c new file mode 100644 index 0000000000..c1500b9fb3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "--param asan-instrument-writes=0 -save-temps" } */ + +volatile int ten = 10; + +int main() { + volatile char x[10]; + x[ten] = 1; + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_store" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c new file mode 100644 index 0000000000..028f8d7152 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c @@ -0,0 +1,68 @@ +/* This tests that when faced with two references to the same memory + location in the same basic block, the second reference should not + be instrumented by the Address Sanitizer. */ + +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +extern char tab[4]; + +static int +test0 () +{ + /* __builtin___asan_report_store1 called 2 times for the two stores + below. */ + tab[0] = 1; + tab[1] = 2; + + /* This load should not be instrumented because it is to the same + memory location as above. */ + char t0 = tab[1]; + + /* Likewise. */ + char t1 = tab[1]; + + return t0 + t1; +} + +__attribute__((noinline, noclone)) static int +test1 (int i) +{ + char foo[4] = {}; + + /*__builtin___asan_report_store1 called 1 time here to instrument + the initialization. */ + foo[i] = 1; + + /*__builtin___asan_report_store_n called once here to instrument + the store to the memory region of tab. */ + __builtin_memset (tab, 3, sizeof (tab)); + + /* There is no instrumentation for the two memset calls below. */ + __builtin_memset (tab, 4, sizeof (tab)); + __builtin_memset (tab, 5, sizeof (tab)); + + /* There is a call to __builtin___asan_report_store_n and a call + to __builtin___asan_report_load_n to instrument the store to + (subset of) the memory region of tab. */ + __builtin_memcpy (&tab[1], foo + i, 3); + + /* This should not generate a __builtin___asan_report_load1 because + the reference to tab[1] has been already instrumented above. */ + return tab[1]; + + /* So for these functions, there should be 3 calls to + __builtin___asan_report_store1. */ +} + +int +main () +{ + return test0 () && test1 (0); +} + +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 3 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c new file mode 100644 index 0000000000..a58411c3af --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c @@ -0,0 +1,26 @@ +/* This tests that when faced with two references to the same memory + location in the same basic block, the second reference should not + be instrumented by the Address Sanitizer. But in case of access to + overlapping regions we must be precise. */ + +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +int +main () +{ + char tab[5]; + + /* Here, we instrument the access at offset 0 and access at offset + 4. */ + __builtin_memset (tab, 1, sizeof (tab)); + /* We instrumented access at offset 0 above already, so only access + at offset 3 is instrumented. */ + __builtin_memset (tab, 1, 3); +} + +/* { dg-final { scan-tree-dump-times "& 7" 3 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c new file mode 100644 index 0000000000..5193ae06f4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c @@ -0,0 +1,18 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +char +foo (__INT32_TYPE__ *p) +{ + /* This generates a __builtin___asan_report_load1. */ + __INT32_TYPE__ ret = *(char *) p; + /* This generates a __builtin___asan_report_store4 depending on the. */ + *p = 26; + return ret; +} + +/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c new file mode 100644 index 0000000000..c3632aa3d2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c @@ -0,0 +1,17 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +void +foo (int *a, char *b, char *c) +{ + /* One check for c[0], one check for a[], one check for c, two checks for b. */ + __builtin_memmove (c, b, a[c[0]]); + /* For a total of 5 checks. */ +} + +/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c new file mode 100644 index 0000000000..077ea34d02 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c @@ -0,0 +1,18 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +void +foo (int *a, char *b, char *c) +{ + /* One check for b[0], one check for a[], 2 checks for c and one checks for b. */ + __builtin_memmove (c, b, a[b[0]]); + /* For a total of 5 checks. */ +} + +/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c new file mode 100644 index 0000000000..6d87104aac --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c @@ -0,0 +1,20 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +void +foo (int *a, char *b, char *c) +{ + /* One check for c[0], one check for a[], one check for c and 2 checks for b. */ + __builtin_memmove (c, b, a[c[0]]); + /* One check for a[], one check for c and one check for b. */ + __builtin_memmove (c, b, a[b[0]]); + /* For a total of 8 checks. */ +} + +/* { dg-final { scan-tree-dump-times "& 7" 8 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c new file mode 100644 index 0000000000..5baa10dcd7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c @@ -0,0 +1,27 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +char e[200]; + +struct S +{ + char a[100]; + char b[100]; +} s; + +int +foo (int *a, char *b, char *c) +{ + /* 2 checks for s.a, 2 checks for e. */ + int d = __builtin_memcmp (s.a, e, 100); + /* One check for s.a and one check for e. */ + d += __builtin_memcmp (s.a, e, 200); + /* For a total of 6 checks. */ + return d; +} + +/* { dg-final { scan-tree-dump-times "& 7" 6 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 4 "sanopt" } } */ +/* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c new file mode 100644 index 0000000000..2a4c0812f3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c @@ -0,0 +1,20 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +char +foo (int *a, char *b, char *c) +{ + /* One check for b[0], one check for a[], two checks for c and one check for b. */ + __builtin_memmove (c, b, a[b[0]]); + /* No checks here. */ + return c[0] + b[0]; + /* For a total of 5 checks. */ +} + +/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c new file mode 100644 index 0000000000..9449de5788 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c @@ -0,0 +1,13 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +__SIZE_TYPE__ +f (char *a) +{ + a[0] = '1'; + return __builtin_strlen (a); +} + +/* { dg-final { scan-tree-dump-times "__asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-use-after-return.c b/gcc/testsuite/c-c++-common/asan/no-use-after-return.c new file mode 100644 index 0000000000..f326e0caee --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-use-after-return.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "--param asan-use-after-return=0 -save-temps" } */ + +extern void f(char *); + +int main() { + char buf[64]; + f(buf); + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_option_detect_stack_use_after_return" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/null-deref-1.c b/gcc/testsuite/c-c++-common/asan/null-deref-1.c new file mode 100644 index 0000000000..6aea9d295f --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/null-deref-1.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-fno-omit-frame-pointer -fno-shrink-wrap" } */ +/* { dg-additional-options "-mno-omit-leaf-frame-pointer" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-shouldfail "asan" } */ + +__attribute__((noinline, noclone)) +static void +NullDeref(int *ptr) +{ + ptr[10]++; +} + +int main() +{ + NullDeref((int*)0); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */ +/* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/pr56330.c b/gcc/testsuite/c-c++-common/asan/pr56330.c new file mode 100644 index 0000000000..25759f4ec9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr56330.c @@ -0,0 +1,24 @@ +/* PR sanitizer/56330 */ +/* { dg-do compile } */ + +char e[200]; + +struct S +{ + char a[100]; + char b[100]; +} s; + +int +foo (void) +{ + int i = __builtin_memcmp (s.a, e, 100); + i += __builtin_memcmp (s.a, e, 200); + return i; +} + +void +bar (int *a, char *b, char *c) +{ + __builtin_memmove (c, b, a[b[0]]); +} diff --git a/gcc/testsuite/c-c++-common/asan/pr59029.c b/gcc/testsuite/c-c++-common/asan/pr59029.c new file mode 100644 index 0000000000..a1319b2720 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr59029.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ + +int +foo () +{ + return __sync_fetch_and_add ((int *) 0, 1); +} diff --git a/gcc/testsuite/c-c++-common/asan/pr59063-1.c b/gcc/testsuite/c-c++-common/asan/pr59063-1.c new file mode 100644 index 0000000000..a22db6a0d8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr59063-1.c @@ -0,0 +1,11 @@ +/* { dg-do run { target { *-*-linux* } } } */ + +#include <time.h> +static int weak_gettime (clockid_t clk_id, struct timespec *tp) + __attribute__((__weakref__("clock_gettime"))); +int main() { + if (!clock_gettime) + return 0; + struct timespec ts; + return weak_gettime(CLOCK_MONOTONIC, &ts); +} diff --git a/gcc/testsuite/c-c++-common/asan/pr59063-2.c b/gcc/testsuite/c-c++-common/asan/pr59063-2.c new file mode 100644 index 0000000000..759b7f24d0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr59063-2.c @@ -0,0 +1,12 @@ +/* { dg-do run { target { *-*-linux* } } } */ +/* { dg-options "-static-libasan" } */ + +#include <time.h> +static int weak_gettime (clockid_t clk_id, struct timespec *tp) + __attribute__((__weakref__("clock_gettime"))); +int main() { + if (!clock_gettime) + return 0; + struct timespec ts; + return weak_gettime(CLOCK_MONOTONIC, &ts); +} diff --git a/gcc/testsuite/c-c++-common/asan/pr61530.c b/gcc/testsuite/c-c++-common/asan/pr61530.c new file mode 100644 index 0000000000..e306a71be9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr61530.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +__attribute__((noinline,noclone)) void +foo (char *a, char *b) { + a[0] = b[0] = 0; + __builtin_memcpy(a, b, 4); +} + +int +main () { + char a, b; + foo (&a, &b); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc/testsuite/c-c++-common/asan/pr62089.c b/gcc/testsuite/c-c++-common/asan/pr62089.c new file mode 100644 index 0000000000..9b92e9bbf1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr62089.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include <stdbool.h> +#include <sanitizer/asan_interface.h> + +struct vfsmount {}; +struct dentry {}; + +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + +struct fs_struct { + int users; + int lock; + int seq; + int umask; + int in_exec; + struct path root, pwd; +}; + +void __attribute__((noinline, noclone)) +copy_fs_struct(struct fs_struct *a, struct fs_struct *b) { + a->root = b->root; +} + +struct fs_struct a, b; + +int +main () { + __asan_poison_memory_region (&a.root, sizeof (a.root)); + copy_fs_struct (&a, &b); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ diff --git a/gcc/testsuite/c-c++-common/asan/pr62140-1.c b/gcc/testsuite/c-c++-common/asan/pr62140-1.c new file mode 100644 index 0000000000..f0b026de2a --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr62140-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-w -fpermissive" } */ + +int memcmp (const void *p, const void *q, int len); + +int f (int *p, int *q, int len) +{ + return memcmp (p, q, len); +} + diff --git a/gcc/testsuite/c-c++-common/asan/pr62140-2.c b/gcc/testsuite/c-c++-common/asan/pr62140-2.c new file mode 100644 index 0000000000..0bb2563aba --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr62140-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-w -fpermissive" } */ + +int strlen (const char *p); + +int f (char *p) +{ + int x = strlen (p); + return x; +} + diff --git a/gcc/testsuite/c-c++-common/asan/pr63638.c b/gcc/testsuite/c-c++-common/asan/pr63638.c new file mode 100644 index 0000000000..a8bafc5aad --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr63638.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +extern +#ifdef __cplusplus +"C" +#endif +void *memcpy (void *, const void *, __SIZE_TYPE__); + +struct S{ + long d0, d1, d2, d3, d4, d5, d6; +}; + +struct S s[6]; + +int f(struct S *p) +{ + memcpy(p, &s[2], sizeof(*p)); + memcpy(p, &s[1], sizeof(*p)); +} + diff --git a/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c b/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c new file mode 100644 index 0000000000..9dbbc85f4f --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c @@ -0,0 +1,22 @@ +/* Check that we properly report mmap failure. */ + +/* { dg-do run { target setrlimit } } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ +/* { dg-require-effective-target hw } */ +/* { dg-shouldfail "asan" } */ + +#include <stdlib.h> +#include <assert.h> +#include <sys/time.h> +#include <sys/resource.h> + +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/asan/sanity-check-pure-c-1.c b/gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c new file mode 100644 index 0000000000..78d15e1aad --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-shouldfail "asan" } */ + +#include <stdlib.h> +int main() { + char *x = (char*)malloc(10); + free(x); + return x[5]; +} + +/* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 \[^\n\r]*(in _*(interceptor_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 \[^\n\r]*(in _*main (\[^\n\r]*sanity-check-pure-c-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output " #0 \[^\n\r]*(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 \[^\n\r]*(in _*main (\[^\n\r]*sanity-check-pure-c-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c b/gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c new file mode 100644 index 0000000000..e50885907d --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/sleep-before-dying-1.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-set-target-env-var ASAN_OPTIONS "sleep_before_dying=1" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-shouldfail "asan" } */ + +#include <stdlib.h> +int main() { + char *x = (char*)malloc(10); + free(x); + return x[5]; +} + +/* { dg-output "Sleeping for 1 second" } */ diff --git a/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c b/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c new file mode 100644 index 0000000000..c717650971 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-memset" } */ +/* { dg-shouldfail "asan" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void *memset (void *, int, __SIZE_TYPE__); + +volatile int ten = 10; + +int main() { + char x[10]; + memset(x, 0, 10); + int res = x[ten]; /* BOOOM */ + return res; +} + +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */ +/* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */ diff --git a/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c b/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c new file mode 100644 index 0000000000..812aa37e2d --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-set-target-env-var ASAN_OPTIONS "strip_path_prefix='/'" } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-shouldfail "asan" } */ + +#include <stdlib.h> +int main() { + char *x = (char*)malloc(10); + free(x); + return x[5]; +} + +/* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ \[(\]?\[^/\]\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c b/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c new file mode 100644 index 0000000000..4833dc7789 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ +/* { dg-shouldfail "asan" } */ + +#include <stdbool.h> +#include <sanitizer/asan_interface.h> + +char a[2] = "0"; + +#ifdef __cplusplus +extern "C" +#endif + +__attribute__((no_sanitize_address, noinline)) __SIZE_TYPE__ +strlen (const char *p) { + + __SIZE_TYPE__ n = 0; + for (; *p; ++n, ++p); + return n; +} + +int main () { + char *p = &a[0]; + asm ("" : "+r"(p)); + __asan_poison_memory_region ((char *)&a[1], 1); + return __builtin_strlen (a); +} + +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strlen-overflow-1.c:26|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c b/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c new file mode 100644 index 0000000000..3ed9fd6dd5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-strncpy" } */ +/* { dg-shouldfail "asan" } */ + +#include <string.h> +#include <stdlib.h> +int main(int argc, char **argv) { + char *hello = (char*)malloc(6); + strcpy(hello, "hello"); + char *short_buffer = (char*)malloc(9); + strncpy(short_buffer, hello, 10); /* BOOM */ + return short_buffer[8]; +} + +/* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c b/gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c new file mode 100644 index 0000000000..23d3db0655 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/swapcontext-test-1.c @@ -0,0 +1,63 @@ +/* Check that ASan plays well with easy cases of makecontext/swapcontext. */ + +/* { dg-do run { target swapcontext } } */ + +#include <stdio.h> +#include <ucontext.h> +#include <unistd.h> + +ucontext_t orig_context; +ucontext_t child_context; + +void Child(int mode) { + char x[32] = {0}; /* Stack gets poisoned. */ + printf("Child: %p\n", x); + /* (a) Do nothing, just return to parent function. + (b) Jump into the original function. Stack remains poisoned unless we do + something. */ + if (mode == 1) { + if (swapcontext(&child_context, &orig_context) < 0) { + perror("swapcontext"); + _exit(0); + } + } +} + +int Run(int arg, int mode) { + int i; + const int kStackSize = 1 << 20; + char child_stack[kStackSize + 1]; + printf("Child stack: %p\n", child_stack); + /* Setup child context. */ + getcontext(&child_context); + child_context.uc_stack.ss_sp = child_stack; + child_context.uc_stack.ss_size = kStackSize / 2; + if (mode == 0) { + child_context.uc_link = &orig_context; + } + makecontext(&child_context, (void (*)())Child, 1, mode); + if (swapcontext(&orig_context, &child_context) < 0) { + perror("swapcontext"); + return 0; + } + /* Touch childs's stack to make sure it's unpoisoned. */ + for (i = 0; i < kStackSize; i++) { + child_stack[i] = i; + } + return child_stack[arg]; +} + +volatile int zero = 0; + +int main(int argc, char **argv) { + int ret = 0; + ret += Run(zero, 0); + printf("Test1 passed\n"); + ret += Run(zero, 1); + printf("Test2 passed\n"); + return ret; +} + +/* { dg-output "WARNING: ASan doesn't fully support makecontext/swapcontext.*" } */ +/* { dg-output "Test1 passed.*" } */ +/* { dg-output "Test2 passed.*" } */ diff --git a/gcc/testsuite/c-c++-common/asan/use-after-free-1.c b/gcc/testsuite/c-c++-common/asan/use-after-free-1.c new file mode 100644 index 0000000000..25e9be827f --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/use-after-free-1.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-fno-builtin-malloc -fno-builtin-free" } */ +/* { dg-shouldfail "asan" } */ + +#include <stdlib.h> +int main() { + char *x = (char*)malloc(10); + free(x); + return x[5]; +} + +/* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */ +/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/use-after-return-1.c b/gcc/testsuite/c-c++-common/asan/use-after-return-1.c new file mode 100644 index 0000000000..49933e531b --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/use-after-return-1.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */ +/* { dg-shouldfail "asan" } */ + +#include <stdio.h> +#include <pthread.h> + +#ifndef kSize +# define kSize 1 +#endif + +#ifndef UseThread +# define UseThread 0 +#endif + +__attribute__((noinline)) +char *Ident(char *x) { + fprintf(stderr, "1: %p\n", x); + return x; +} + +__attribute__((noinline)) +char *Func1() { + char local[kSize]; + return Ident(local); +} + +__attribute__((noinline)) +void Func2(char *x) { + fprintf(stderr, "2: %p\n", x); + *x = 1; +} + +void *Thread(void *unused) { + Func2(Func1()); + return NULL; +} + +int main(int argc, char **argv) { +#if UseThread + pthread_t t; + pthread_create(&t, 0, Thread, 0); + pthread_join(t, 0); +#else + Func2(Func1()); +#endif + return 0; +} + +/* { dg-output "WRITE of size 1 at .* thread T0.*" } */ +/* { dg-output " #0.*(Func2)?.*use-after-return-1.(c:31)?.*" } */ +/* { dg-output "is located in stack of thread T0 at offset.*" } */ +/* { dg-output "\'local\' <== Memory access at offset 32 is inside this variable" } */ |