diff options
| author | Mattias Andrée <m@maandree.se> | 2026-03-20 23:35:38 +0100 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-03-20 23:37:25 +0100 |
| commit | db49c933fe34a54947dbc7df381fa1700dc1e74f (patch) | |
| tree | 7f59c27e6187c8ed4614101916e7bee66a7a0ecf | |
| download | sigsegv-recovery-db49c933fe34a54947dbc7df381fa1700dc1e74f.tar.gz sigsegv-recovery-db49c933fe34a54947dbc7df381fa1700dc1e74f.tar.bz2 sigsegv-recovery-db49c933fe34a54947dbc7df381fa1700dc1e74f.tar.xz | |
Signed-off-by: Mattias Andrée <m@maandree.se>
| -rw-r--r-- | .gitignore | 18 | ||||
| -rw-r--r-- | LICENSE | 15 | ||||
| -rw-r--r-- | Makefile | 28 | ||||
| -rw-r--r-- | README | 2 | ||||
| -rw-r--r-- | config.mk | 8 | ||||
| -rw-r--r-- | sigsegv-recovery.c | 46 | ||||
| -rw-r--r-- | stackoverflow-recovery.c | 75 |
7 files changed, 192 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..69ef5dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +*\#* +*~ +*.o +*.a +*.t +*.lo +*.to +*.su +*.so +*.so.* +*.dll +*.dylib +*.gch +*.gcov +*.gcno +*.gcda +/sigsegv-recovery +/stackoverflow-recovery @@ -0,0 +1,15 @@ +ISC License + +© 2026 Mattias Andrée <m@maandree.se> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..eb2a03e --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + +OBJ =\ + sigsegv-recovery.o\ + stackoverflow-recovery.o + +HDR = + +all: $(OBJ:.o=) +$(OBJ): $(HDR) + +.c.o: + $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +.o: + $(CC) -o $@ $< $(LDFLAGS) + +clean: + -rm -f -- *.o *.a *.lo *.su + -rm -f -- $(OBJ:.o=) + +.SUFFIXES: +.SUFFIXES: .o .c + +.PHONY: all clean @@ -0,0 +1,2 @@ +This is a just a simple example demonstrating how to make a +program recover after a segmentation violation or stack overflow. diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..f4adf12 --- /dev/null +++ b/config.mk @@ -0,0 +1,8 @@ +PREFIX = /usr +MANPREFIX = $(PREFIX)/share/man + +CC = c99 + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CFLAGS = +LDFLAGS = diff --git a/sigsegv-recovery.c b/sigsegv-recovery.c new file mode 100644 index 0000000..b69449b --- /dev/null +++ b/sigsegv-recovery.c @@ -0,0 +1,46 @@ +/* See LICENSE file for copyright and license details. */ +#include <setjmp.h> +#include <signal.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> + + +int *volatile just_null = NULL; + +static jmp_buf jmpenv; + + +static void +sigsegv(int signo) +{ + (void) signo; + + siglongjmp(jmpenv, 1); +} + + +int +main(void) +{ + volatile int sum = 0; + volatile int i; + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + 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 null dereference\n", i); + sum += *just_null; + } else { + printf("%i: after null dereference\n", i); + } + } + + fflush(stdout); + return sum; +} 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; +} |
