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  
       9  ucontext_t orig_context;
      10  ucontext_t child_context;
      11  
      12  void 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  
      26  int 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  
      50  volatile int zero = 0;
      51  
      52  int main(int argc, char **argv) {
      53    int ret = 0;
      54    ret += Run(zero, 0);
      55    fprintf(stderr, "Test1 passed\n");
      56    ret += Run(zero, 1);
      57    fprintf(stderr, "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.*" } */