Blame src/regression/sigaltstack.c

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