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