xref: /llvm-project/compiler-rt/test/asan/TestCases/Linux/stack-overflow-sigbus.cpp (revision c2fd3b76f21632fa617a18c50dc9dff84b1a6538)
1 // Test ASan detection of stack-overflow condition when Linux sends SIGBUS.
2 
3 // RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
4 
5 // Issue #109771
6 // XFAIL: target={{sparc.*-.*-linux.*}}
7 
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <sys/resource.h>
15 
16 const int BS = 1024;
17 volatile char x;
18 volatile int y = 1;
19 
20 void recursive_func(char *p) {
21   char buf[BS];
22   buf[rand() % BS] = 1;
23   buf[rand() % BS] = 2;
24   x = buf[rand() % BS];
25   if (y)
26     recursive_func(buf);
27   x = 1; // prevent tail call optimization
28   // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}}
29 }
30 
31 void LimitStackAndReexec(int argc, char **argv) {
32   struct rlimit rlim;
33   int res = getrlimit(RLIMIT_STACK, &rlim);
34   assert(res == 0);
35   if (rlim.rlim_cur == RLIM_INFINITY) {
36     rlim.rlim_cur = 256 * 1024;
37     res = setrlimit(RLIMIT_STACK, &rlim);
38     assert(res == 0);
39 
40     execv(argv[0], argv);
41     assert(0 && "unreachable");
42   }
43 }
44 
45 int main(int argc, char **argv) {
46   LimitStackAndReexec(argc, argv);
47 
48   // Map some memory just before the start of the current stack vma.
49   // When the stack grows down and crashes into it, Linux can send
50   // SIGBUS instead of SIGSEGV. See:
51   // http://lkml.iu.edu/hypermail/linux/kernel/1008.1/02299.html
52   const long pagesize = sysconf(_SC_PAGESIZE);
53   FILE *f = fopen("/proc/self/maps", "r");
54   char a[1000];
55   void *p = 0;
56   while (fgets(a, sizeof a, f)) {
57     if (strstr(a, "[stack]")) {
58       unsigned long addr;
59       if (sscanf(a, "%lx", &addr) == 1)
60         p = mmap((void *)(addr - 4 * pagesize), pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
61     }
62   }
63   assert(p);
64 
65   recursive_func(0);
66   return 0;
67 }
68