sigaltstack regression test
authorSzabolcs Nagy <nsz@port70.net>
Wed, 19 Mar 2014 04:36:54 +0000 (05:36 +0100)
committerSzabolcs Nagy <nsz@port70.net>
Wed, 19 Mar 2014 04:36:54 +0000 (05:36 +0100)
src/regression/sigaltstack.c [new file with mode: 0644]

diff --git a/src/regression/sigaltstack.c b/src/regression/sigaltstack.c
new file mode 100644 (file)
index 0000000..f4ed470
--- /dev/null
@@ -0,0 +1,88 @@
+// commit: 6871fd773dcedbf056317d5d5e87b4859e97c4a4 2011-03-10
+// commit: 9505bfbc40fec217820abad7142663eda60cd6be 2014-03-18
+// catching stackoverflow SIGSEGV using sigaltstack
+// mips stack_t is inconsistent with other archs
+#define _XOPEN_SOURCE 700
+#include <signal.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "test.h"
+
+#define T(f) ((f)==0 || (t_error(#f " failed: %s\n", strerror(errno)),0))
+
+static char stack[SIGSTKSZ];
+static sigjmp_buf sbuf;
+static volatile sig_atomic_t state;
+
+static void handler(int sig)
+{
+       uintptr_t i;
+       stack_t ss;
+
+       if (state!=1)
+               t_error("handler is not invoked in fillstack (after sigsetjmp returned 0), "
+                       "state is %d, want 1\n", state);
+       state++;
+
+       i = (uintptr_t)&i;
+       if (i < (uintptr_t)stack || i >= (uintptr_t)stack+SIGSTKSZ)
+               t_error("signal handler was not invoked on the altstack\n");
+
+       T(sigaltstack(0, &ss));
+       if (ss.ss_flags != SS_ONSTACK)
+               t_error("ss_flags is not SS_ONSTACK in the signal handler\n");
+
+       siglongjmp(sbuf, 1);
+}
+
+static unsigned fillstack(unsigned x)
+{
+       x++;
+       if (x==0) {
+               t_error("wrap around\n");
+               return x;
+       }
+       return fillstack(fillstack(x)) + 1;
+}
+
+int main(void)
+{
+       stack_t ss;
+       struct sigaction sa;
+
+       ss.ss_sp = stack;
+       ss.ss_size = sizeof stack;
+       ss.ss_flags = 0;
+       sa.sa_handler = handler;
+       sa.sa_flags = SA_ONSTACK;
+
+       T(sigaltstack(&ss, 0));
+       T(sigfillset(&sa.sa_mask));
+       T(sigaction(SIGSEGV, &sa, 0));
+       if (sigsetjmp(sbuf,0) == 0) {
+               state++;
+               fillstack(0);
+               t_error("infinite recursion finished\n");
+       }
+       if (state != 2)
+               t_error("sigsetjmp returned non-zero before running handler, "
+                       "state is %d, want 2\n", state);
+
+       errno = 0;
+       ss.ss_size = MINSIGSTKSZ-1;
+       if (sigaltstack(&ss, 0) != -1 || errno != ENOMEM)
+               t_error("sigaltstack with stack size < MINSIGSTKSZ should have failed with ENOMEM, "
+                       "got %s\n", strerror(errno));
+       errno = 0;
+       ss.ss_flags = -1;
+       ss.ss_size = MINSIGSTKSZ;
+       if (sigaltstack(&ss, 0) != -1 || errno != EINVAL)
+               t_error("sigaltstack with bad ss_flags should have failed with EINVAL, "
+                       "got %s\n", strerror(errno));
+       errno = 0;
+       T(sigaltstack(0, 0));
+
+       return t_status;
+}