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:
@@ -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 */
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user