mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-29 22:53:03 +00:00 
			
		
		
		
	Prevent await inside janet_call - address #1531
This was partially implemented before, but not in the case where the await or other signal itself was created by a C function. We have to separate code paths for generating signals - one via normal returns in janet_vm_continue, and the other via longjump. This adds handling for the longjump case, as well as improved messaging.
This commit is contained in:
		| @@ -62,6 +62,13 @@ JANET_NO_RETURN static void janet_top_level_signal(const char *msg) { | ||||
|  | ||||
| void janet_signalv(JanetSignal sig, Janet message) { | ||||
|     if (janet_vm.return_reg != NULL) { | ||||
|         /* Should match logic in janet_call for coercing everything not ok to an error (no awaits, yields, etc.) */ | ||||
|         if (janet_vm.coerce_error && sig != JANET_SIGNAL_OK) { | ||||
|             if (sig != JANET_SIGNAL_ERROR) { | ||||
|                 message = janet_wrap_string(janet_formatc("%v coerced from %s to error", message, janet_signal_names[sig])); | ||||
|             } | ||||
|             sig = JANET_SIGNAL_ERROR; | ||||
|         } | ||||
|         *janet_vm.return_reg = message; | ||||
|         if (NULL != janet_vm.fiber) { | ||||
|             janet_vm.fiber->flags |= JANET_FIBER_DID_LONGJUMP; | ||||
|   | ||||
| @@ -100,6 +100,7 @@ struct JanetVM { | ||||
|      * return point for panics. */ | ||||
|     jmp_buf *signal_buf; | ||||
|     Janet *return_reg; | ||||
|     int coerce_error; | ||||
|  | ||||
|     /* The global registry for c functions. Used to store meta-data | ||||
|      * along with otherwise bare c function pointers. */ | ||||
|   | ||||
| @@ -1373,7 +1373,10 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) { | ||||
|  | ||||
|     /* Run vm */ | ||||
|     janet_vm.fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP; | ||||
|     int old_coerce_error = janet_vm.coerce_error; | ||||
|     janet_vm.coerce_error = 1; | ||||
|     JanetSignal signal = run_vm(janet_vm.fiber, janet_wrap_nil()); | ||||
|     janet_vm.coerce_error = old_coerce_error; | ||||
|  | ||||
|     /* Teardown */ | ||||
|     janet_vm.stackn = oldn; | ||||
| @@ -1384,6 +1387,10 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) { | ||||
|     } | ||||
|  | ||||
|     if (signal != JANET_SIGNAL_OK) { | ||||
|         /* Should match logic in janet_signalv */ | ||||
|         if (signal != JANET_SIGNAL_ERROR) { | ||||
|             *janet_vm.return_reg = janet_wrap_string(janet_formatc("%v coerced from %s to error", *janet_vm.return_reg, janet_signal_names[signal])); | ||||
|         } | ||||
|         janet_panicv(*janet_vm.return_reg); | ||||
|     } | ||||
|  | ||||
| @@ -1430,8 +1437,10 @@ void janet_try_init(JanetTryState *state) { | ||||
|     state->vm_fiber = janet_vm.fiber; | ||||
|     state->vm_jmp_buf = janet_vm.signal_buf; | ||||
|     state->vm_return_reg = janet_vm.return_reg; | ||||
|     state->coerce_error = janet_vm.coerce_error; | ||||
|     janet_vm.return_reg = &(state->payload); | ||||
|     janet_vm.signal_buf = &(state->buf); | ||||
|     janet_vm.coerce_error = 0; | ||||
| } | ||||
|  | ||||
| void janet_restore(JanetTryState *state) { | ||||
| @@ -1440,6 +1449,7 @@ void janet_restore(JanetTryState *state) { | ||||
|     janet_vm.fiber = state->vm_fiber; | ||||
|     janet_vm.signal_buf = state->vm_jmp_buf; | ||||
|     janet_vm.return_reg = state->vm_return_reg; | ||||
|     janet_vm.coerce_error = state->coerce_error; | ||||
| } | ||||
|  | ||||
| static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) { | ||||
|   | ||||
| @@ -1261,6 +1261,7 @@ typedef struct { | ||||
|     /* new state */ | ||||
|     jmp_buf buf; | ||||
|     Janet payload; | ||||
|     int coerce_error; | ||||
| } JanetTryState; | ||||
|  | ||||
| /***** END SECTION TYPES *****/ | ||||
|   | ||||
| @@ -465,4 +465,13 @@ | ||||
| # Close chat server | ||||
| (:close chat-server) | ||||
|  | ||||
| # Issue #1531 | ||||
| (def c (ev/chan 0)) | ||||
| (ev/spawn (while (def x (ev/take c)))) | ||||
| (defn print-to-chan [x] (ev/give c x)) | ||||
| (assert-error "coerce await inside janet_call to error" | ||||
|               (with-dyns [*out* print-to-chan] | ||||
|                 (pp :foo))) | ||||
| (ev/chan-close c) | ||||
|  | ||||
| (end-suite) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose