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