#include #include #include static union { char buffer[SIGSTKSZ]; long double ld; long u; void *p; } alternate_signal_stack; #if STACK_DIRECTION # define find_stack_direction(ptr) STACK_DIRECTION #else static int find_stack_direction (char const *addr) { char dummy; return (! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1); } #endif static void segv_handler (int signo, siginfo_t *info, void *context) { if (0 < info->si_code) { ucontext_t const *user_context = context; char const *stack_min = user_context->uc_stack.ss_sp; size_t stack_size = user_context->uc_stack.ss_size; char const *faulting_address = info->si_addr; size_t s = faulting_address - stack_min; size_t page_size = sysconf (_SC_PAGESIZE); if (find_stack_direction (0) < 0) s += page_size; if (s < stack_size + page_size) _exit (0); } _exit (1); } static int c_stack_action (void) { stack_t st; struct sigaction act; int r; st.ss_flags = 0; st.ss_sp = alternate_signal_stack.buffer; st.ss_size = sizeof alternate_signal_stack.buffer; r = sigaltstack (&st, 0); if (r != 0) return r; sigemptyset (&act.sa_mask); act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; act.sa_sigaction = segv_handler; return sigaction (SIGSEGV, &act, 0); } static int recurse (char *p) { char array[500]; array[0] = 1; return *p + recurse (array); } int main (void) { c_stack_action (); return recurse ("\1"); }