summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-06-24 22:01:38 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-06-24 22:01:38 -0700
commit817cd5991d6304a2368824acbfc0b0e95c2aa7a7 (patch)
tree4aa5e7b112cdf41d2a713e42562f9699c8839dd3
parent1c1685861e0d304f60f0669c6dbd5005349262e4 (diff)
downloadtxr-817cd5991d6304a2368824acbfc0b0e95c2aa7a7.tar.gz
txr-817cd5991d6304a2368824acbfc0b0e95c2aa7a7.tar.bz2
txr-817cd5991d6304a2368824acbfc0b0e95c2aa7a7.zip
signals: disable stack overflow in handler.
* signal.c (sig_handler): For a is_cpu_exception signal, we temporarily disable the stack limit. It might be executing on the sigaltstack buffer, which is almost certainly below the stack limit. * tests/012/stack.tl: New test case. We raise a SIGSEGV and check that in the handler, the stack limit is disabled, and that we can executed code.
-rw-r--r--signal.c4
-rw-r--r--tests/012/stack.tl11
2 files changed, 15 insertions, 0 deletions
diff --git a/signal.c b/signal.c
index 53e4e499..ad5c9849 100644
--- a/signal.c
+++ b/signal.c
@@ -81,11 +81,14 @@ static void sig_handler(int sig)
int exc = is_cpu_exception(sig);
int ic = interrupt_count++;
int in_interrupt = ic > 0;
+ val *stack_lim;
if (exc) {
gc = gc_state(0);
+ stack_lim = gc_stack_limit;
as = async_sig_enabled;
async_sig_enabled = 1;
+ gc_stack_limit = 0;
}
sig_reload_cache();
@@ -109,6 +112,7 @@ static void sig_handler(int sig)
}
if (exc) {
+ gc_stack_limit = stack_lim;
async_sig_enabled = as;
gc_state(gc);
}
diff --git a/tests/012/stack.tl b/tests/012/stack.tl
index a8d06487..879d3d27 100644
--- a/tests/012/stack.tl
+++ b/tests/012/stack.tl
@@ -29,3 +29,14 @@
(set-stack-limit orig) nil
(set-stack-limit 65536) orig
(set-stack-limit orig) 65536)
+
+(set-sig-handler sig-segv
+ (lambda (signal async-p)
+ (assert (null (get-stack-limit)))
+ (throw 'out)))
+
+(test
+ (catch
+ (raise sig-segv)
+ (out () :sig))
+ :sig)