1 // RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s 2 // RUN: %clangxx_asan -O1 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s 3 // RUN: %clangxx_asan -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s 4 // RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s 5 // RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t 6 // Regression test for a CHECK failure with small stack size and large frame. 7 // RUN: %clangxx_asan -O3 %s -pthread -o %t -DkSize=10000 -DUseThread -DkStackSize=65536 && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s 8 // 9 // Test that we can find UAR in a thread other than main: 10 // 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 11 // 12 // Test the max_uar_stack_size_log/min_uar_stack_size_log flag. 13 // 14 // 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 15 // 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 16 17 #include <stdio.h> 18 #include <pthread.h> 19 20 #ifndef kSize 21 # define kSize 1 22 #endif 23 24 #ifndef UseThread 25 # define UseThread 0 26 #endif 27 28 #ifndef kStackSize 29 # define kStackSize 0 30 #endif 31 32 __attribute__((noinline)) 33 char *Ident(char *x) { 34 fprintf(stderr, "1: %p\n", x); 35 return x; 36 } 37 38 __attribute__((noinline)) 39 char *Func1() { 40 char local[kSize]; 41 return Ident(local); 42 } 43 44 __attribute__((noinline)) 45 void Func2(char *x) { 46 fprintf(stderr, "2: %p\n", x); 47 *x = 1; 48 // CHECK: WRITE of size 1 {{.*}} thread T0 49 // CHECK: #0{{.*}}Func2{{.*}}stack-use-after-return.cc:[[@LINE-2]] 50 // CHECK: is located in stack of thread T0 at offset 51 // CHECK: 'local' <== Memory access at offset {{16|32}} is inside this variable 52 // THREAD: WRITE of size 1 {{.*}} thread T{{[1-9]}} 53 // THREAD: #0{{.*}}Func2{{.*}}stack-use-after-return.cc:[[@LINE-6]] 54 // THREAD: is located in stack of thread T{{[1-9]}} at offset 55 // THREAD: 'local' <== Memory access at offset {{16|32}} is inside this variable 56 // CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20 57 // CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24 58 } 59 60 void *Thread(void *unused) { 61 Func2(Func1()); 62 return NULL; 63 } 64 65 int main(int argc, char **argv) { 66 #if UseThread 67 pthread_attr_t attr; 68 pthread_attr_init(&attr); 69 if (kStackSize > 0) 70 pthread_attr_setstacksize(&attr, kStackSize); 71 pthread_t t; 72 pthread_create(&t, &attr, Thread, 0); 73 pthread_attr_destroy(&attr); 74 pthread_join(t, 0); 75 #else 76 Func2(Func1()); 77 #endif 78 return 0; 79 } 80