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
29const int BS = 1024;
30volatile char x;
31volatile int y = 1;
32volatile int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13;
33
34void 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(parent_frame_address: (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
86void *ThreadFn(void* unused) {
87 recursive_func(parent_frame_address: (uintptr_t)__builtin_frame_address(0));
88 return 0;
89}
90
91void LimitStackAndReexec(int argc, char **argv) {
92 struct rlimit rlim;
93 int res = getrlimit(RLIMIT_STACK, rlimits: &rlim);
94 assert(res == 0);
95 if (rlim.rlim_cur == RLIM_INFINITY) {
96 rlim.rlim_cur = 256 * 1024;
97 res = setrlimit(RLIMIT_STACK, rlimits: &rlim);
98 assert(res == 0);
99
100 execv(path: argv[0], argv: argv);
101 assert(0 && "unreachable");
102 }
103}
104
105int 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(parent_frame_address: (uintptr_t)__builtin_frame_address(0));
113#endif
114 return 0;
115}
116

source code of compiler-rt/test/asan/TestCases/Posix/stack-overflow.cpp