16a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// RUN: %clangxx_asan %s -pthread -o %t
22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// RUN: %clangxx_asan -O3 %s -pthread -o %t
586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
76a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// REQUIRES: stable-runtime
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <assert.h>
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <stdio.h>
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <pthread.h>
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sanitizer/asan_interface.h>
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic const int kNumThreads = 2;
1586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const int kLeftRedzoneSize = sizeof(void *) * 4;
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *Thread(void *unused)  {
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void *fake_stack = __asan_get_current_fake_stack();
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char var[15];
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (fake_stack) {
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    fprintf(stderr, "fake stack found: %p; var: %p\n", fake_stack, var);
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // CHECK1: fake stack found
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // CHECK1: fake stack found
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    void *beg, *end;
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    void *real_stack =
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        __asan_addr_is_in_fake_stack(fake_stack, &var[0], &beg, &end);
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    assert(real_stack);
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    assert((char*)beg <= (char*)&var[0]);
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    assert((char*)end > (char*)&var[0]);
3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    for (int i = -kLeftRedzoneSize; i < 15; i++) {
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      void *beg1, *end1;
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      char *ptr = &var[0] + i;
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      void *real_stack1 =
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          __asan_addr_is_in_fake_stack(fake_stack, ptr, &beg1, &end1);
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      assert(real_stack == real_stack1);
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      assert(beg == beg1);
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      assert(end == end1);
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } else {
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    fprintf(stderr, "no fake stack\n");
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // CHECK0: no fake stack
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // CHECK0: no fake stack
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return NULL;
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint main(int argc, char **argv) {
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_t t[kNumThreads];
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (int i = 0; i < kNumThreads; i++)
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    pthread_create(&t[i], 0, Thread, 0);
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (int i = 0; i < kNumThreads; i++)
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    pthread_join(t[i], 0);
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
55