1 // Check that if LSan finds that SP doesn't point into thread stack (e.g.
2 // if swapcontext is used), LSan will not hit the guard page.
3 // RUN: %clang_lsan %s -o %t && %run %t
4 // Missing 'getcontext' and 'makecontext' on Android.
5 // UNSUPPORTED: android
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <pthread.h>
12 #include <ucontext.h>
13
14 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
15 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
16 int ctxfunc_started = 0;
17
die(const char * msg,int err)18 static void die(const char* msg, int err) {
19 if (err == 0)
20 err = errno;
21 fprintf(stderr, "%s: %s\n", msg, strerror(err));
22 exit(EXIT_FAILURE);
23 }
24
ctxfunc()25 static void ctxfunc() {
26 pthread_mutex_lock(&mutex);
27 ctxfunc_started = 1;
28 // printf("ctxfunc\n");
29 pthread_cond_signal(&cond);
30 pthread_mutex_unlock(&mutex);
31 // Leave this context alive when the program exits.
32 for (;;);
33 }
34
thread(void * arg)35 static void* thread(void* arg) {
36 (void)arg;
37 ucontext_t ctx;
38 void* stack;
39
40 if (getcontext(&ctx) < 0)
41 die("getcontext", 0);
42 stack = malloc(1 << 12);
43 if (stack == NULL)
44 die("malloc", 0);
45 ctx.uc_stack.ss_sp = stack;
46 ctx.uc_stack.ss_size = 1 << 12;
47 makecontext(&ctx, ctxfunc, 0);
48 setcontext(&ctx);
49 die("setcontext", 0);
50 return NULL;
51 }
52
main()53 int main() {
54 pthread_t tid;
55 int i;
56
57 pthread_mutex_lock(&mutex);
58 i = pthread_create(&tid, NULL, thread, NULL);
59 if (i != 0)
60 die("pthread_create", i);
61 while (!ctxfunc_started) pthread_cond_wait(&cond, &mutex);
62 pthread_mutex_unlock(&mutex);
63 return 0;
64 }
65