1 | // RUN: %clang_safestack %s -pthread -o %t |
2 | // RUN: %run %t |
3 | |
4 | // Test unsafe stack deallocation with custom stack sizes, in particular ensure |
5 | // that we correctly deallocate small stacks and don't accidentally deallocate |
6 | // adjacent memory. |
7 | |
8 | #include <pthread.h> |
9 | #include <stdlib.h> |
10 | #include <string.h> |
11 | #include <unistd.h> |
12 | |
13 | volatile int step = 0; |
14 | |
15 | void *wait_until(void *ptr) { |
16 | while ((int)ptr != step) |
17 | usleep(useconds: 1000); |
18 | |
19 | volatile char buf[64]; |
20 | buf[0] = 0; |
21 | |
22 | return NULL; |
23 | } |
24 | |
25 | int main(int argc, char **argv) { |
26 | pthread_t t1, t2, t3; |
27 | |
28 | pthread_attr_t small_stack_attr; |
29 | pthread_attr_init(attr: &small_stack_attr); |
30 | pthread_attr_setstacksize(attr: &small_stack_attr, stacksize: 65536); |
31 | |
32 | if (pthread_create(newthread: &t3, NULL, start_routine: wait_until, arg: (void *)3)) |
33 | abort(); |
34 | if (pthread_create(newthread: &t1, attr: &small_stack_attr, start_routine: wait_until, arg: (void *)1)) |
35 | abort(); |
36 | if (pthread_create(newthread: &t2, NULL, start_routine: wait_until, arg: (void *)2)) |
37 | abort(); |
38 | |
39 | step = 1; |
40 | if (pthread_join(th: t1, NULL)) |
41 | abort(); |
42 | |
43 | step = 2; |
44 | if (pthread_join(th: t2, NULL)) |
45 | abort(); |
46 | |
47 | step = 3; |
48 | if (pthread_join(th: t3, NULL)) |
49 | abort(); |
50 | |
51 | pthread_attr_destroy(attr: &small_stack_attr); |
52 | return 0; |
53 | } |
54 | |