1 // RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
2 // RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
3 // XFAIL: windows-msvc
4 
5 // FIXME: Fix this test under GCC.
6 // REQUIRES: Clang
7 
8 // FIXME: Fix this test for dynamic runtime on arm linux.
9 // UNSUPPORTED: (arm-linux || armhf-linux) && asan-dynamic-runtime
10 
11 // UNSUPPORTED: ios
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 
17 __attribute__((noinline))
pretend_to_do_something(char * x)18 char *pretend_to_do_something(char *x) {
19   __asm__ __volatile__("" : : "r" (x) : "memory");
20   return x;
21 }
22 
23 __attribute__((noinline))
LeakStack()24 char *LeakStack() {
25   char x[1024];
26   memset(x, 0, sizeof(x));
27   return pretend_to_do_something(x);
28 }
29 
30 template<size_t kFrameSize>
31 __attribute__((noinline))
RecursiveFunctionWithStackFrame(int depth)32 void RecursiveFunctionWithStackFrame(int depth) {
33   if (depth <= 0) return;
34   char x[kFrameSize];
35   x[0] = depth;
36   pretend_to_do_something(x);
37   RecursiveFunctionWithStackFrame<kFrameSize>(depth - 1);
38 }
39 
main(int argc,char ** argv)40 int main(int argc, char **argv) {
41 #ifdef _MSC_VER
42   // FIXME: This test crashes on Windows and raises a dialog. Avoid running it
43   // in addition to XFAILing it.
44   return 42;
45 #endif
46 
47   int n_iter = argc >= 2 ? atoi(argv[1]) : 1000;
48   int depth  = argc >= 3 ? atoi(argv[2]) : 500;
49   for (int i = 0; i < n_iter; i++) {
50     RecursiveFunctionWithStackFrame<10>(depth);
51     RecursiveFunctionWithStackFrame<100>(depth);
52     RecursiveFunctionWithStackFrame<500>(depth);
53     RecursiveFunctionWithStackFrame<1024>(depth);
54     RecursiveFunctionWithStackFrame<2000>(depth);
55     // The stack size is tight for the main thread in multithread
56     // environment on FreeBSD and NetBSD.
57 #if !defined(__FreeBSD__) && !defined(__NetBSD__)
58     RecursiveFunctionWithStackFrame<5000>(depth);
59     RecursiveFunctionWithStackFrame<10000>(depth);
60 #endif
61   }
62   char *stale_stack = LeakStack();
63   RecursiveFunctionWithStackFrame<1024>(10);
64   stale_stack[100]++;
65   // CHECK: ERROR: AddressSanitizer: stack-use-after-return on address
66   // CHECK: is located in stack of thread T0 at offset {{116|132}} in frame
67   // CHECK:  in LeakStack{{.*}}heavy_uar_test.cpp:
68   // CHECK: [{{16|32}}, {{1040|1056}}) 'x'
69   return 0;
70 }
71