• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Check that ASan plays well with easy cases of makecontext/swapcontext.
2 
3 // RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
4 // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
5 // RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
6 // RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
7 //
8 // This test is too sublte to try on non-x86 arch for now.
9 // REQUIRES: x86_64-supported-target,i386-supported-target
10 
11 #include <stdio.h>
12 #include <ucontext.h>
13 #include <unistd.h>
14 
15 ucontext_t orig_context;
16 ucontext_t child_context;
17 
18 const int kStackSize = 1 << 20;
19 
20 __attribute__((noinline))
Throw()21 void Throw() {
22   throw 1;
23 }
24 
25 __attribute__((noinline))
ThrowAndCatch()26 void ThrowAndCatch() {
27   try {
28     Throw();
29   } catch(int a) {
30     printf("ThrowAndCatch: %d\n", a);
31   }
32 }
33 
Child(int mode)34 void Child(int mode) {
35   char x[32] = {0};  // Stack gets poisoned.
36   printf("Child: %p\n", x);
37   ThrowAndCatch();  // Simulate __asan_handle_no_return().
38   // (a) Do nothing, just return to parent function.
39   // (b) Jump into the original function. Stack remains poisoned unless we do
40   //     something.
41   if (mode == 1) {
42     if (swapcontext(&child_context, &orig_context) < 0) {
43       perror("swapcontext");
44       _exit(0);
45     }
46   }
47 }
48 
Run(int arg,int mode,char * child_stack)49 int Run(int arg, int mode, char *child_stack) {
50   printf("Child stack: %p\n", child_stack);
51   // Setup child context.
52   getcontext(&child_context);
53   child_context.uc_stack.ss_sp = child_stack;
54   child_context.uc_stack.ss_size = kStackSize / 2;
55   if (mode == 0) {
56     child_context.uc_link = &orig_context;
57   }
58   makecontext(&child_context, (void (*)())Child, 1, mode);
59   if (swapcontext(&orig_context, &child_context) < 0) {
60     perror("swapcontext");
61     return 0;
62   }
63   // Touch childs's stack to make sure it's unpoisoned.
64   for (int i = 0; i < kStackSize; i++) {
65     child_stack[i] = i;
66   }
67   return child_stack[arg];
68 }
69 
main(int argc,char ** argv)70 int main(int argc, char **argv) {
71   char stack[kStackSize + 1];
72   // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
73   int ret = 0;
74   ret += Run(argc - 1, 0, stack);
75   printf("Test1 passed\n");
76   // CHECK: Test1 passed
77   ret += Run(argc - 1, 1, stack);
78   printf("Test2 passed\n");
79   // CHECK: Test2 passed
80   char *heap = new char[kStackSize + 1];
81   ret += Run(argc - 1, 0, heap);
82   printf("Test3 passed\n");
83   // CHECK: Test3 passed
84   ret += Run(argc - 1, 1, heap);
85   printf("Test4 passed\n");
86   // CHECK: Test4 passed
87 
88   delete [] heap;
89   return ret;
90 }
91