1 // RUN: %clangxx_asan -fsanitize=use-after-return -O0 %s -o %t && \ 2 // RUN: not %t 2>&1 | FileCheck %s 3 // RUN: %clangxx_asan -fsanitize=use-after-return -O2 %s -o %t && \ 4 // RUN: not %t 2>&1 | FileCheck %s 5 6 #include <stdio.h> 7 #include <string.h> 8 #include <stdlib.h> 9 10 __attribute__((noinline)) 11 char *pretend_to_do_something(char *x) { 12 __asm__ __volatile__("" : : "r" (x) : "memory"); 13 return x; 14 } 15 16 __attribute__((noinline)) 17 char *LeakStack() { 18 char x[1024]; 19 memset(x, 0, sizeof(x)); 20 return pretend_to_do_something(x); 21 } 22 23 template<size_t kFrameSize> 24 __attribute__((noinline)) 25 void RecuriveFunctionWithStackFrame(int depth) { 26 if (depth <= 0) return; 27 char x[kFrameSize]; 28 x[0] = depth; 29 pretend_to_do_something(x); 30 RecuriveFunctionWithStackFrame<kFrameSize>(depth - 1); 31 } 32 33 int main(int argc, char **argv) { 34 int n_iter = argc >= 2 ? atoi(argv[1]) : 1000; 35 int depth = argc >= 3 ? atoi(argv[2]) : 500; 36 for (int i = 0; i < n_iter; i++) { 37 RecuriveFunctionWithStackFrame<10>(depth); 38 RecuriveFunctionWithStackFrame<100>(depth); 39 RecuriveFunctionWithStackFrame<500>(depth); 40 RecuriveFunctionWithStackFrame<1024>(depth); 41 RecuriveFunctionWithStackFrame<2000>(depth); 42 RecuriveFunctionWithStackFrame<5000>(depth); 43 RecuriveFunctionWithStackFrame<10000>(depth); 44 } 45 char *stale_stack = LeakStack(); 46 RecuriveFunctionWithStackFrame<1024>(10); 47 stale_stack[100]++; 48 // CHECK: ERROR: AddressSanitizer: stack-use-after-return on address 49 // CHECK: is located in stack of thread T0 at offset 132 in frame 50 // CHECK: in LeakStack(){{.*}}heavy_uar_test.cc: 51 // CHECK: [32, 1056) 'x' 52 return 0; 53 } 54