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))
26char *pretend_to_do_something(char *x) {
27 __asm__ __volatile__("" : : "r" (x) : "memory");
28 return x;
29}
30
31__attribute__((noinline))
32char *LeakStack() {
33 char x[1024];
34 memset(s: x, c: 0, n: sizeof(x));
35 return pretend_to_do_something(x);
36}
37
38template<size_t kFrameSize>
39__attribute__((noinline))
40void 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
48int 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(nptr: argv[1]) : 1000;
56 int depth = argc >= 3 ? atoi(nptr: 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>(depth: 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

source code of compiler-rt/test/asan/TestCases/heavy_uar_test.cpp