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 15ucontext_t orig_context; 16ucontext_t child_context; 17 18const int kStackSize = 1 << 20; 19 20__attribute__((noinline)) 21void Throw() { 22 throw 1; 23} 24 25__attribute__((noinline)) 26void ThrowAndCatch() { 27 try { 28 Throw(); 29 } catch(int a) { 30 printf("ThrowAndCatch: %d\n", a); 31 } 32} 33 34void 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 49int 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 70int 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