1 // Test ASan detection of stack-overflow condition. 2 3 // RUN: %clangxx_asan -O0 %s -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 4 // RUN: %clangxx_asan -O3 %s -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 5 // RUN: %clangxx_asan -O0 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 6 // RUN: %clangxx_asan -O3 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 7 // RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 8 // RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 9 10 // RUN: %clangxx_asan -O0 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 11 // RUN: %clangxx_asan -O3 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 12 // RUN: %clangxx_asan -O0 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 13 // RUN: %clangxx_asan -O3 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 14 // RUN: %clangxx_asan -O0 %s -DTHREAD -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 15 // RUN: %clangxx_asan -O3 %s -DTHREAD -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s 16 // RUN: not %run %t 2>&1 | FileCheck %s 17 // REQUIRES: stable-runtime 18 19 // Issue #109771 20 // XFAIL: target={{sparc.*-.*-linux.*}} 21 22 // UNSUPPORTED: ios 23 24 #include <assert.h> 25 #include <stdlib.h> 26 #include <pthread.h> 27 #include <unistd.h> 28 #include <sys/time.h> 29 #include <sys/resource.h> 30 #include <sanitizer/asan_interface.h> 31 32 const int BS = 1024; 33 volatile char x; 34 volatile int y = 1; 35 volatile int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13; 36 37 void recursive_func(uintptr_t parent_frame_address) { 38 #if defined(SMALL_FRAME) 39 char *buf = 0; 40 #elif defined(SAVE_ALL_THE_REGISTERS) 41 char *buf = 0; 42 int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13; 43 t0 = z0; 44 t1 = z1; 45 t2 = z2; 46 t3 = z3; 47 t4 = z4; 48 t5 = z5; 49 t6 = z6; 50 t7 = z7; 51 t8 = z8; 52 t9 = z9; 53 t10 = z10; 54 t11 = z11; 55 t12 = z12; 56 t13 = z13; 57 58 z0 = t0; 59 z1 = t1; 60 z2 = t2; 61 z3 = t3; 62 z4 = t4; 63 z5 = t5; 64 z6 = t6; 65 z7 = t7; 66 z8 = t8; 67 z9 = t9; 68 z10 = t10; 69 z11 = t11; 70 z12 = t12; 71 z13 = t13; 72 #else 73 char buf[BS]; 74 // Check that the stack grows in the righ direction, unless we use fake stack. 75 assert(parent_frame_address > (uintptr_t)__builtin_frame_address(0)); 76 buf[rand() % BS] = 1; 77 buf[rand() % BS] = 2; 78 x = buf[rand() % BS]; 79 #endif 80 if (y) 81 recursive_func((uintptr_t)__builtin_frame_address(0)); 82 x = 1; // prevent tail call optimization 83 // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}} 84 // If stack overflow happens during function prologue, stack trace may be 85 // corrupted. Unwind tables are not always 100% exact there. 86 // For this reason, we don't do any further checks. 87 } 88 89 void *ThreadFn(void* unused) { 90 recursive_func((uintptr_t)__builtin_frame_address(0)); 91 return 0; 92 } 93 94 void LimitStackAndReexec(int argc, char **argv) { 95 struct rlimit rlim; 96 int res = getrlimit(RLIMIT_STACK, &rlim); 97 assert(res == 0); 98 if (rlim.rlim_cur == RLIM_INFINITY) { 99 rlim.rlim_cur = 256 * 1024; 100 res = setrlimit(RLIMIT_STACK, &rlim); 101 assert(res == 0); 102 103 execv(argv[0], argv); 104 assert(0 && "unreachable"); 105 } 106 } 107 108 int main(int argc, char **argv) { 109 LimitStackAndReexec(argc, argv); 110 #ifdef THREAD 111 pthread_t t; 112 pthread_create(&t, 0, ThreadFn, 0); 113 pthread_join(t, 0); 114 #else 115 recursive_func((uintptr_t)__builtin_frame_address(0)); 116 #endif 117 return 0; 118 } 119