sigaltstack regression test
[libc-test] / src / regression / sigaltstack.c
1 // commit: 6871fd773dcedbf056317d5d5e87b4859e97c4a4 2011-03-10
2 // commit: 9505bfbc40fec217820abad7142663eda60cd6be 2014-03-18
3 // catching stackoverflow SIGSEGV using sigaltstack
4 // mips stack_t is inconsistent with other archs
5 #define _XOPEN_SOURCE 700
6 #include <signal.h>
7 #include <setjmp.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <errno.h>
11 #include "test.h"
12
13 #define T(f) ((f)==0 || (t_error(#f " failed: %s\n", strerror(errno)),0))
14
15 static char stack[SIGSTKSZ];
16 static sigjmp_buf sbuf;
17 static volatile sig_atomic_t state;
18
19 static void handler(int sig)
20 {
21         uintptr_t i;
22         stack_t ss;
23
24         if (state!=1)
25                 t_error("handler is not invoked in fillstack (after sigsetjmp returned 0), "
26                         "state is %d, want 1\n", state);
27         state++;
28
29         i = (uintptr_t)&i;
30         if (i < (uintptr_t)stack || i >= (uintptr_t)stack+SIGSTKSZ)
31                 t_error("signal handler was not invoked on the altstack\n");
32
33         T(sigaltstack(0, &ss));
34         if (ss.ss_flags != SS_ONSTACK)
35                 t_error("ss_flags is not SS_ONSTACK in the signal handler\n");
36
37         siglongjmp(sbuf, 1);
38 }
39
40 static unsigned fillstack(unsigned x)
41 {
42         x++;
43         if (x==0) {
44                 t_error("wrap around\n");
45                 return x;
46         }
47         return fillstack(fillstack(x)) + 1;
48 }
49
50 int main(void)
51 {
52         stack_t ss;
53         struct sigaction sa;
54
55         ss.ss_sp = stack;
56         ss.ss_size = sizeof stack;
57         ss.ss_flags = 0;
58         sa.sa_handler = handler;
59         sa.sa_flags = SA_ONSTACK;
60
61         T(sigaltstack(&ss, 0));
62         T(sigfillset(&sa.sa_mask));
63         T(sigaction(SIGSEGV, &sa, 0));
64         if (sigsetjmp(sbuf,0) == 0) {
65                 state++;
66                 fillstack(0);
67                 t_error("infinite recursion finished\n");
68         }
69         if (state != 2)
70                 t_error("sigsetjmp returned non-zero before running handler, "
71                         "state is %d, want 2\n", state);
72
73         errno = 0;
74         ss.ss_size = MINSIGSTKSZ-1;
75         if (sigaltstack(&ss, 0) != -1 || errno != ENOMEM)
76                 t_error("sigaltstack with stack size < MINSIGSTKSZ should have failed with ENOMEM, "
77                         "got %s\n", strerror(errno));
78         errno = 0;
79         ss.ss_flags = -1;
80         ss.ss_size = MINSIGSTKSZ;
81         if (sigaltstack(&ss, 0) != -1 || errno != EINVAL)
82                 t_error("sigaltstack with bad ss_flags should have failed with EINVAL, "
83                         "got %s\n", strerror(errno));
84         errno = 0;
85         T(sigaltstack(0, 0));
86
87         return t_status;
88 }