mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +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 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 */ | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose