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-target-arch 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)) 21 void Throw() { 22 throw 1; 23 } 24 25 __attribute__((noinline)) 26 void ThrowAndCatch() { 27 try { 28 Throw(); 29 } catch(int a) { 30 printf("ThrowAndCatch: %d\n", a); 31 } 32 } 33 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 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 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