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