Home | History | Annotate | Download | only in Posix
      1 // Test ASan detection of stack-overflow condition.
      2 
      3 // RUN: %clangxx_asan -O0 %s -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
      4 // RUN: %clangxx_asan -O3 %s -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
      5 // RUN: %clangxx_asan -O0 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
      6 // RUN: %clangxx_asan -O3 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
      7 // RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
      8 // RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
      9 
     10 // RUN: %clangxx_asan -O0 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
     11 // RUN: %clangxx_asan -O3 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
     12 // RUN: %clangxx_asan -O0 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
     13 // RUN: %clangxx_asan -O3 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
     14 // RUN: %clangxx_asan -O0 %s -DTHREAD -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
     15 // RUN: %clangxx_asan -O3 %s -DTHREAD -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
     16 // RUN: not %run %t 2>&1 | FileCheck %s
     17 // REQUIRES: stable-runtime
     18 
     19 #include <assert.h>
     20 #include <stdlib.h>
     21 #include <pthread.h>
     22 #include <unistd.h>
     23 #include <sys/time.h>
     24 #include <sys/resource.h>
     25 #include <sanitizer/asan_interface.h>
     26 
     27 const int BS = 1024;
     28 volatile char x;
     29 volatile int y = 1;
     30 volatile int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13;
     31 
     32 void recursive_func(char *p) {
     33 #if defined(SMALL_FRAME)
     34   char *buf = 0;
     35 #elif defined(SAVE_ALL_THE_REGISTERS)
     36   char *buf = 0;
     37   int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13;
     38   t0 = z0;
     39   t1 = z1;
     40   t2 = z2;
     41   t3 = z3;
     42   t4 = z4;
     43   t5 = z5;
     44   t6 = z6;
     45   t7 = z7;
     46   t8 = z8;
     47   t9 = z9;
     48   t10 = z10;
     49   t11 = z11;
     50   t12 = z12;
     51   t13 = z13;
     52 
     53   z0 = t0;
     54   z1 = t1;
     55   z2 = t2;
     56   z3 = t3;
     57   z4 = t4;
     58   z5 = t5;
     59   z6 = t6;
     60   z7 = t7;
     61   z8 = t8;
     62   z9 = t9;
     63   z10 = t10;
     64   z11 = t11;
     65   z12 = t12;
     66   z13 = t13;
     67 #else
     68   char buf[BS];
     69   // Check that the stack grows in the righ direction, unless we use fake stack.
     70   if (p && !__asan_get_current_fake_stack())
     71     assert(p - buf >= BS);
     72   buf[rand() % BS] = 1;
     73   buf[rand() % BS] = 2;
     74   x = buf[rand() % BS];
     75 #endif
     76   if (y)
     77     recursive_func(buf);
     78   x = 1; // prevent tail call optimization
     79   // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}}
     80   // If stack overflow happens during function prologue, stack trace may be
     81   // corrupted. Unwind tables are not always 100% exact there.
     82   // For this reason, we don't do any further checks.
     83 }
     84 
     85 void *ThreadFn(void* unused) {
     86   recursive_func(0);
     87   return 0;
     88 }
     89 
     90 void LimitStackAndReexec(int argc, char **argv) {
     91   struct rlimit rlim;
     92   int res = getrlimit(RLIMIT_STACK, &rlim);
     93   assert(res == 0);
     94   if (rlim.rlim_cur == RLIM_INFINITY) {
     95     rlim.rlim_cur = 256 * 1024;
     96     res = setrlimit(RLIMIT_STACK, &rlim);
     97     assert(res == 0);
     98 
     99     execv(argv[0], argv);
    100     assert(0 && "unreachable");
    101   }
    102 }
    103 
    104 int main(int argc, char **argv) {
    105   LimitStackAndReexec(argc, argv);
    106 #ifdef THREAD
    107   pthread_t t;
    108   pthread_create(&t, 0, ThreadFn, 0);
    109   pthread_join(t, 0);
    110 #else
    111   recursive_func(0);
    112 #endif
    113   return 0;
    114 }
    115