1/* Check that ASan plays well with easy cases of makecontext/swapcontext. */ 2 3/* { dg-do run { target swapcontext } } */ 4 5#include <stdio.h> 6#include <ucontext.h> 7#include <unistd.h> 8 9ucontext_t orig_context; 10ucontext_t child_context; 11 12void Child(int mode) { 13 char x[32] = {0}; /* Stack gets poisoned. */ 14 printf("Child: %p\n", x); 15 /* (a) Do nothing, just return to parent function. 16 (b) Jump into the original function. Stack remains poisoned unless we do 17 something. */ 18 if (mode == 1) { 19 if (swapcontext(&child_context, &orig_context) < 0) { 20 perror("swapcontext"); 21 _exit(0); 22 } 23 } 24} 25 26int Run(int arg, int mode) { 27 int i; 28 const int kStackSize = 1 << 20; 29 char child_stack[kStackSize + 1]; 30 printf("Child stack: %p\n", child_stack); 31 /* Setup child context. */ 32 getcontext(&child_context); 33 child_context.uc_stack.ss_sp = child_stack; 34 child_context.uc_stack.ss_size = kStackSize / 2; 35 if (mode == 0) { 36 child_context.uc_link = &orig_context; 37 } 38 makecontext(&child_context, (void (*)())Child, 1, mode); 39 if (swapcontext(&orig_context, &child_context) < 0) { 40 perror("swapcontext"); 41 return 0; 42 } 43 /* Touch childs's stack to make sure it's unpoisoned. */ 44 for (i = 0; i < kStackSize; i++) { 45 child_stack[i] = i; 46 } 47 return child_stack[arg]; 48} 49 50volatile int zero = 0; 51 52int main(int argc, char **argv) { 53 int ret = 0; 54 ret += Run(zero, 0); 55 printf("Test1 passed\n"); 56 ret += Run(zero, 1); 57 printf("Test2 passed\n"); 58 return ret; 59} 60 61/* { dg-output "WARNING: ASan doesn't fully support makecontext/swapcontext.*" } */ 62/* { dg-output "Test1 passed.*" } */ 63/* { dg-output "Test2 passed.*" } */ 64