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