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