1
0
mirror of https://github.com/janet-lang/janet synced 2025-11-09 20:13:02 +00:00

Fix undefined behavior bug with errors.

janet_vm_return_reg should only be set when janet_continue
is called. Otherwise, a panic may dump it's error message in
the wrong place, resulting in undefined behavior (often showing
the last return value or worse, segfaulting).
This commit is contained in:
Calvin Rose
2019-04-10 23:29:40 -04:00
parent d514eab627
commit 1596511175
2 changed files with 9 additions and 8 deletions

View File

@@ -578,7 +578,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee)); janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame); Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
janet_fiber_popframe(fiber); janet_fiber_popframe(fiber);
/*if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);*/
stack = fiber->data + fiber->frame; stack = fiber->data + fiber->frame;
stack[A] = ret; stack[A] = ret;
vm_checkgc_pcnext(); vm_checkgc_pcnext();
@@ -638,6 +637,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig)))
vm_return(sig, retreg); vm_return(sig, retreg);
fiber->child = NULL; fiber->child = NULL;
stack = fiber->data + fiber->frame;
stack[A] = retreg; stack[A] = retreg;
vm_checkgc_pcnext(); vm_checkgc_pcnext();
} }
@@ -749,9 +749,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
} }
Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) { Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
Janet ret;
Janet *old_return_reg = janet_vm_return_reg;
/* Check entry conditions */ /* Check entry conditions */
if (!janet_vm_fiber) if (!janet_vm_fiber)
janet_panic("janet_call failed because there is no current fiber"); janet_panic("janet_call failed because there is no current fiber");
@@ -768,7 +765,6 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
/* Set up */ /* Set up */
int32_t oldn = janet_vm_stackn++; int32_t oldn = janet_vm_stackn++;
int handle = janet_gclock(); int handle = janet_gclock();
janet_vm_return_reg = &ret;
/* Run vm */ /* Run vm */
JanetSignal signal = run_vm(janet_vm_fiber, JanetSignal signal = run_vm(janet_vm_fiber,
@@ -776,13 +772,12 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
JANET_STATUS_ALIVE); JANET_STATUS_ALIVE);
/* Teardown */ /* Teardown */
janet_vm_return_reg = old_return_reg;
janet_vm_stackn = oldn; janet_vm_stackn = oldn;
janet_gcunlock(handle); janet_gcunlock(handle);
if (signal != JANET_SIGNAL_OK) janet_panicv(ret); if (signal != JANET_SIGNAL_OK) janet_panicv(*janet_vm_return_reg);
return ret; return *janet_vm_return_reg;
} }
/* Enter the main vm loop */ /* Enter the main vm loop */

View File

@@ -351,6 +351,12 @@
(def t (put @{} :hi 1)) (def t (put @{} :hi 1))
(assert (deep= t @{:hi 1}) "regression #24") (assert (deep= t @{:hi 1}) "regression #24")
# Peg swallowing errors
(assert (try (peg/match ~(/ '1 ,(fn [x] (nil x))) "x") ([err] err))
"errors should not be swallowed")
(assert (try ((fn [x] (nil x))) ([err] err))
"errors should not be swallowed 2")
# Tuple types # Tuple types
(assert (= (tuple/type '(1 2 3)) :parens) "normal tuple") (assert (= (tuple/type '(1 2 3)) :parens) "normal tuple")