diff options
Diffstat (limited to 'stackoverflow-recovery.c')
| -rw-r--r-- | stackoverflow-recovery.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/stackoverflow-recovery.c b/stackoverflow-recovery.c new file mode 100644 index 0000000..436c8c7 --- /dev/null +++ b/stackoverflow-recovery.c @@ -0,0 +1,75 @@ +/* See LICENSE file for copyright and license details. */ +#include <setjmp.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +unsigned volatile just_one = 1; + +static jmp_buf jmpenv; + + +static void +sigsegv(int signo) +{ + (void) signo; + + siglongjmp(jmpenv, 1); +} + + +static unsigned +overflow2(size_t depth) +{ + if (!depth) + return just_one; + depth -= 1u; + return overflow2(depth) + overflow2(depth); +} + + +static unsigned +overflow(void) +{ + return overflow2(SIZE_MAX); +} + + +int +main(void) +{ + volatile unsigned sum = 0; + volatile int i; + struct sigaction sa; + stack_t ss; + + ss.ss_sp = malloc((size_t)SIGSTKSZ); + if (!ss.ss_sp) + return 1; + ss.ss_size = (size_t)SIGSTKSZ; + ss.ss_flags = 0; + if (sigaltstack(&ss, NULL)) + return 2; + + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_ONSTACK; + sa.sa_handler = &sigsegv; + sigfillset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, NULL); + + for (i = 1; i <= 10; i++) { + if (!sigsetjmp(jmpenv, 1)) { + printf("%i: before overflow dereference\n", i); + sum += overflow(); + } else { + printf("%i: after overflow dereference\n", i); + } + } + + fflush(stdout); + return (int)sum; +} |
