1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O1 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t
// RUN: %clangxx_asan -O0 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O1 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O2 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O3 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O3 %s -pthread -o %t -fsanitize-address-use-after-return=never && %run %t
// Regression test for a CHECK failure with small stack size and large frame.
// RUN: %clangxx_asan -O3 %s -pthread -o %t -DkSize=10000 -DUseThread -DkStackSize=131072 && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
// RUN: %clangxx_asan -O3 %s -pthread -o %t -DkSize=10000 -DUseThread -DkStackSize=131072 -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
//
// Test that we can find UAR in a thread other than main (UAR mode: runtime):
// RUN: %clangxx_asan -DUseThread -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
//
// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
// (uses the previous)
//
// RUN: %env_asan_opts=detect_stack_use_after_return=1:max_uar_stack_size_log=20:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
// RUN: %env_asan_opts=detect_stack_use_after_return=1:min_uar_stack_size_log=24:max_uar_stack_size_log=24:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s
//
// Test that we can find UAR in a thread other than main (UAR mode: always):
// RUN: %clangxx_asan -DUseThread -O2 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
//
// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
// (uses the previous)
//
// RUN: %env_asan_opts=max_uar_stack_size_log=20:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
// RUN: %env_asan_opts=min_uar_stack_size_log=24:max_uar_stack_size_log=24:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s
// This test runs out of stack on AArch64.
// UNSUPPORTED: target=aarch64{{.*}}
// stack size log lower than expected
// XFAIL: target={{.*(freebsd|netbsd).*}}
// FIXME: Fix this test for dynamic runtime on arm linux.
// UNSUPPORTED: (arm-linux || armhf-linux) && asan-dynamic-runtime
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef kSize
# define kSize 1
#endif
#ifndef UseThread
# define UseThread 0
#endif
#ifndef kStackSize
# define kStackSize 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;
// CHECK: WRITE of size 1 {{.*}} thread T0
// CHECK: #0{{.*}}Func2{{.*}}stack-use-after-return.cpp:[[@LINE-2]]
// CHECK: is located in stack of thread T0 at offset
// CHECK: 'local'{{.*}} <== Memory access at offset {{16|32}} is inside this variable
// THREAD: WRITE of size 1 {{.*}} thread T{{[1-9]}}
// THREAD: #0{{.*}}Func2{{.*}}stack-use-after-return.cpp:[[@LINE-6]]
// THREAD: is located in stack of thread T{{[1-9]}} at offset
// THREAD: 'local'{{.*}} <== Memory access at offset {{16|32}} is inside this variable
// CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20
// CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24
}
void *Thread(void *unused) {
Func2(Func1());
return NULL;
}
int main(int argc, char **argv) {
#if UseThread
pthread_attr_t attr;
pthread_attr_init(&attr);
if (kStackSize > 0) {
size_t desired_stack_size = kStackSize;
#ifdef PTHREAD_STACK_MIN
if (desired_stack_size < PTHREAD_STACK_MIN) {
desired_stack_size = PTHREAD_STACK_MIN;
}
#endif
int ret = pthread_attr_setstacksize(&attr, desired_stack_size);
if (ret != 0) {
fprintf(stderr, "pthread_attr_setstacksize returned %d\n", ret);
abort();
}
size_t stacksize_check;
ret = pthread_attr_getstacksize(&attr, &stacksize_check);
if (ret != 0) {
fprintf(stderr, "pthread_attr_getstacksize returned %d\n", ret);
abort();
}
if (stacksize_check != desired_stack_size) {
fprintf(stderr, "Unable to set stack size to %d, the stack size is %d.\n",
(int)desired_stack_size, (int)stacksize_check);
abort();
}
}
pthread_t t;
pthread_create(&t, &attr, Thread, 0);
pthread_attr_destroy(&attr);
pthread_join(t, 0);
#else
Func2(Func1());
#endif
return 0;
}
|