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