aboutsummaryrefslogtreecommitdiff
path: root/test/asan/TestCases/stack-overflow.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/asan/TestCases/stack-overflow.cc')
-rw-r--r--test/asan/TestCases/stack-overflow.cc114
1 files changed, 114 insertions, 0 deletions
diff --git a/test/asan/TestCases/stack-overflow.cc b/test/asan/TestCases/stack-overflow.cc
new file mode 100644
index 000000000000..7542d56b6db8
--- /dev/null
+++ b/test/asan/TestCases/stack-overflow.cc
@@ -0,0 +1,114 @@
+// Test ASan detection of stack-overflow condition.
+
+// RUN: %clangxx_asan -O0 %s -DSMALL_FRAME -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DSMALL_FRAME -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -O0 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DTHREAD -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -pthread -o %t && env ASAN_OPTIONS=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+// REQUIRES: stable-runtime
+
+#include <assert.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sanitizer/asan_interface.h>
+
+const int BS = 1024;
+volatile char x;
+volatile int y = 1;
+volatile int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13;
+
+void recursive_func(char *p) {
+#if defined(SMALL_FRAME)
+ char *buf = 0;
+#elif defined(SAVE_ALL_THE_REGISTERS)
+ char *buf = 0;
+ int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13;
+ t0 = z0;
+ t1 = z1;
+ t2 = z2;
+ t3 = z3;
+ t4 = z4;
+ t5 = z5;
+ t6 = z6;
+ t7 = z7;
+ t8 = z8;
+ t9 = z9;
+ t10 = z10;
+ t11 = z11;
+ t12 = z12;
+ t13 = z13;
+
+ z0 = t0;
+ z1 = t1;
+ z2 = t2;
+ z3 = t3;
+ z4 = t4;
+ z5 = t5;
+ z6 = t6;
+ z7 = t7;
+ z8 = t8;
+ z9 = t9;
+ z10 = t10;
+ z11 = t11;
+ z12 = t12;
+ z13 = t13;
+#else
+ char buf[BS];
+ // Check that the stack grows in the righ direction, unless we use fake stack.
+ if (p && !__asan_get_current_fake_stack())
+ assert(p - buf >= BS);
+ buf[rand() % BS] = 1;
+ buf[rand() % BS] = 2;
+ x = buf[rand() % BS];
+#endif
+ if (y)
+ recursive_func(buf);
+ x = 1; // prevent tail call optimization
+ // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}}
+ // If stack overflow happens during function prologue, stack trace may be
+ // corrupted. Unwind tables are not always 100% exact there.
+ // For this reason, we don't do any further checks.
+}
+
+void *ThreadFn(void* unused) {
+ recursive_func(0);
+ return 0;
+}
+
+void LimitStackAndReexec(int argc, char **argv) {
+ struct rlimit rlim;
+ int res = getrlimit(RLIMIT_STACK, &rlim);
+ assert(res == 0);
+ if (rlim.rlim_cur == RLIM_INFINITY) {
+ rlim.rlim_cur = 128 * 1024;
+ res = setrlimit(RLIMIT_STACK, &rlim);
+ assert(res == 0);
+
+ execv(argv[0], argv);
+ assert(0 && "unreachable");
+ }
+}
+
+int main(int argc, char **argv) {
+ LimitStackAndReexec(argc, argv);
+#ifdef THREAD
+ pthread_t t;
+ pthread_create(&t, 0, ThreadFn, 0);
+ pthread_join(t, 0);
+#else
+ recursive_func(0);
+#endif
+ return 0;
+}