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