aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-03-20 23:35:38 +0100
committerMattias Andrée <m@maandree.se>2026-03-20 23:37:25 +0100
commitdb49c933fe34a54947dbc7df381fa1700dc1e74f (patch)
tree7f59c27e6187c8ed4614101916e7bee66a7a0ecf
downloadsigsegv-recovery-db49c933fe34a54947dbc7df381fa1700dc1e74f.tar.gz
sigsegv-recovery-db49c933fe34a54947dbc7df381fa1700dc1e74f.tar.bz2
sigsegv-recovery-db49c933fe34a54947dbc7df381fa1700dc1e74f.tar.xz
First commitHEADmaster
Signed-off-by: Mattias Andrée <m@maandree.se>
-rw-r--r--.gitignore18
-rw-r--r--LICENSE15
-rw-r--r--Makefile28
-rw-r--r--README2
-rw-r--r--config.mk8
-rw-r--r--sigsegv-recovery.c46
-rw-r--r--stackoverflow-recovery.c75
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
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1634eae
--- /dev/null
+++ b/LICENSE
@@ -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
diff --git a/README b/README
new file mode 100644
index 0000000..c42d5be
--- /dev/null
+++ b/README
@@ -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;
+}