1799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
2799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
3799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// XFAIL: arm-linux-gnueabi,win32
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FIXME: Fix this test under GCC.
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// REQUIRES: Clang
72c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany
82c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany#include <stdio.h>
92c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany#include <string.h>
1037f9464fc0fa4df2acf04264c52ba542d0e3d3fbKostya Serebryany#include <stdlib.h>
112c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany
122c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany__attribute__((noinline))
1371c9e9ebd85afdea5d0b56cdf9138fc5afc609cbKostya Serebryanychar *pretend_to_do_something(char *x) {
142c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  __asm__ __volatile__("" : : "r" (x) : "memory");
152c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  return x;
162c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany}
172c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany
182c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany__attribute__((noinline))
192c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryanychar *LeakStack() {
202c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  char x[1024];
212c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  memset(x, 0, sizeof(x));
222c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  return pretend_to_do_something(x);
232c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany}
242c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany
25fecbf270853bda8aa6c14917fdfee840493a061bKostya Serebryanytemplate<size_t kFrameSize>
262c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany__attribute__((noinline))
2786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid RecursiveFunctionWithStackFrame(int depth) {
282c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  if (depth <= 0) return;
29fecbf270853bda8aa6c14917fdfee840493a061bKostya Serebryany  char x[kFrameSize];
3071c9e9ebd85afdea5d0b56cdf9138fc5afc609cbKostya Serebryany  x[0] = depth;
312c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  pretend_to_do_something(x);
3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  RecursiveFunctionWithStackFrame<kFrameSize>(depth - 1);
332c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany}
342c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany
352c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryanyint main(int argc, char **argv) {
36799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifdef _MSC_VER
37799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // FIXME: This test crashes on Windows and raises a dialog. Avoid running it
38799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // in addition to XFAILing it.
39799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return 42;
40799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif
41799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar
4237f9464fc0fa4df2acf04264c52ba542d0e3d3fbKostya Serebryany  int n_iter = argc >= 2 ? atoi(argv[1]) : 1000;
4371c9e9ebd85afdea5d0b56cdf9138fc5afc609cbKostya Serebryany  int depth  = argc >= 3 ? atoi(argv[2]) : 500;
44fecbf270853bda8aa6c14917fdfee840493a061bKostya Serebryany  for (int i = 0; i < n_iter; i++) {
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<10>(depth);
4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<100>(depth);
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<500>(depth);
4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<1024>(depth);
4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<2000>(depth);
5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // The stack size is tight for the main thread in multithread
5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // environment on FreeBSD.
5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if !defined(__FreeBSD__)
5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<5000>(depth);
5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    RecursiveFunctionWithStackFrame<10000>(depth);
5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
56fecbf270853bda8aa6c14917fdfee840493a061bKostya Serebryany  }
5771c9e9ebd85afdea5d0b56cdf9138fc5afc609cbKostya Serebryany  char *stale_stack = LeakStack();
5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  RecursiveFunctionWithStackFrame<1024>(10);
592c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  stale_stack[100]++;
602c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  // CHECK: ERROR: AddressSanitizer: stack-use-after-return on address
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // CHECK: is located in stack of thread T0 at offset {{116|132}} in frame
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // CHECK:  in LeakStack{{.*}}heavy_uar_test.cc:
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // CHECK: [{{16|32}}, {{1040|1056}}) 'x'
642c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany  return 0;
652c02f6327f51243fc0ba17992cecb2857fa8bdf8Kostya Serebryany}
66