1 // Check that ASan plays well with easy cases of makecontext/swapcontext. 2 3 // RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | FileCheck %s 4 // RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1 | FileCheck %s 5 // RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1 | FileCheck %s 6 // RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | FileCheck %s 7 // RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1 | FileCheck %s 8 // RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | FileCheck %s 9 // RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | FileCheck %s 10 // RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | FileCheck %s 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 void Child(int mode) { 20 char x[32] = {0}; // Stack gets poisoned. 21 printf("Child: %p\n", x); 22 // (a) Do nothing, just return to parent function. 23 // (b) Jump into the original function. Stack remains poisoned unless we do 24 // something. 25 if (mode == 1) { 26 if (swapcontext(&child_context, &orig_context) < 0) { 27 perror("swapcontext"); 28 _exit(0); 29 } 30 } 31 } 32 33 int Run(int arg, int mode) { 34 const int kStackSize = 1 << 20; 35 char child_stack[kStackSize + 1]; 36 printf("Child stack: %p\n", child_stack); 37 // Setup child context. 38 getcontext(&child_context); 39 child_context.uc_stack.ss_sp = child_stack; 40 child_context.uc_stack.ss_size = kStackSize / 2; 41 if (mode == 0) { 42 child_context.uc_link = &orig_context; 43 } 44 makecontext(&child_context, (void (*)())Child, 1, mode); 45 if (swapcontext(&orig_context, &child_context) < 0) { 46 perror("swapcontext"); 47 return 0; 48 } 49 // Touch childs's stack to make sure it's unpoisoned. 50 for (int i = 0; i < kStackSize; i++) { 51 child_stack[i] = i; 52 } 53 return child_stack[arg]; 54 } 55 56 int main(int argc, char **argv) { 57 // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext 58 int ret = 0; 59 ret += Run(argc - 1, 0); 60 printf("Test1 passed\n"); 61 // CHECK: Test1 passed 62 ret += Run(argc - 1, 1); 63 printf("Test2 passed\n"); 64 // CHECK: Test2 passed 65 return ret; 66 } 67