From 1596511175ba9234d6f883813affa8db30f0d3bb Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 10 Apr 2019 23:29:40 -0400 Subject: [PATCH] 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). --- src/core/vm.c | 11 +++-------- test/suite3.janet | 6 ++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/vm.c b/src/core/vm.c index 7a6a17d3..6513a587 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -578,7 +578,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee)); Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame); janet_fiber_popframe(fiber); - /*if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);*/ stack = fiber->data + fiber->frame; stack[A] = ret; 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))) vm_return(sig, retreg); fiber->child = NULL; + stack = fiber->data + fiber->frame; stack[A] = retreg; 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 ret; - Janet *old_return_reg = janet_vm_return_reg; - /* Check entry conditions */ if (!janet_vm_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 */ int32_t oldn = janet_vm_stackn++; int handle = janet_gclock(); - janet_vm_return_reg = &ret; /* Run vm */ 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); /* Teardown */ - janet_vm_return_reg = old_return_reg; janet_vm_stackn = oldn; 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 */ diff --git a/test/suite3.janet b/test/suite3.janet index 097eb26b..00fce95d 100644 --- a/test/suite3.janet +++ b/test/suite3.janet @@ -351,6 +351,12 @@ (def t (put @{} :hi 1)) (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 (assert (= (tuple/type '(1 2 3)) :parens) "normal tuple")