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