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)26char *pretend_to_do_something(char *x) { 27 __asm__ __volatile__("" : : "r" (x) : "memory"); 28 return x; 29 } 30 31 __attribute__((noinline)) LeakStack()32char *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)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 main(int argc,char ** argv)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(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