84ca2a131cf248a0eeb59a8d50c22f8ea13dd240
[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 <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include "test.h"
11
12 #define T(f) ((f)==0 || (t_error(#f " failed: %s\n", strerror(errno)),0))
13
14 static char stack[SIGSTKSZ];
15
16 static void handler(int sig)
17 {
18         uintptr_t i;
19         stack_t ss;
20
21         i = (uintptr_t)&i;
22         if (i < (uintptr_t)stack || i >= (uintptr_t)stack+SIGSTKSZ)
23                 t_error("signal handler was not invoked on the altstack\n");
24
25         T(sigaltstack(0, &ss));
26         if (ss.ss_flags != SS_ONSTACK)
27                 t_error("ss_flags is not SS_ONSTACK in the signal handler\n");
28 }
29
30 int main(void)
31 {
32         stack_t ss;
33         struct sigaction sa;
34
35         ss.ss_sp = stack;
36         ss.ss_size = sizeof stack;
37         ss.ss_flags = 0;
38         sa.sa_handler = handler;
39         sa.sa_flags = SA_ONSTACK;
40
41         T(sigaltstack(&ss, 0));
42         T(sigfillset(&sa.sa_mask));
43         T(sigaction(SIGUSR1, &sa, 0));
44         T(raise(SIGUSR1));
45
46         errno = 0;
47         ss.ss_size = MINSIGSTKSZ-1;
48         if (sigaltstack(&ss, 0) != -1 || errno != ENOMEM)
49                 t_error("sigaltstack with stack size < MINSIGSTKSZ should have failed with ENOMEM, "
50                         "got %s\n", strerror(errno));
51         errno = 0;
52         ss.ss_flags = -1;
53         ss.ss_size = MINSIGSTKSZ;
54         if (sigaltstack(&ss, 0) != -1 || errno != EINVAL)
55                 t_error("sigaltstack with bad ss_flags should have failed with EINVAL, "
56                         "got %s\n", strerror(errno));
57         errno = 0;
58         T(sigaltstack(0, 0));
59
60         return t_status;
61 }