Skip to content

Commit 4daecc9

Browse files
committed
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.
1 parent a85eaca commit 4daecc9

File tree

5 files changed

+28
-0
lines changed

5 files changed

+28
-0
lines changed

src/core/capi.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ JANET_NO_RETURN static void janet_top_level_signal(const char *msg) {
6262

6363
void janet_signalv(JanetSignal sig, Janet message) {
6464
if (janet_vm.return_reg != NULL) {
65+
/* Should match logic in janet_call for coercing everything not ok to an error (no awaits, yields, etc.) */
66+
if (janet_vm.coerce_error && sig != JANET_SIGNAL_OK) {
67+
if (sig != JANET_SIGNAL_ERROR) {
68+
message = janet_wrap_string(janet_formatc("%v coerced from %s to error", message, janet_signal_names[sig]));
69+
}
70+
sig = JANET_SIGNAL_ERROR;
71+
}
6572
*janet_vm.return_reg = message;
6673
if (NULL != janet_vm.fiber) {
6774
janet_vm.fiber->flags |= JANET_FIBER_DID_LONGJUMP;

src/core/state.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct JanetVM {
100100
* return point for panics. */
101101
jmp_buf *signal_buf;
102102
Janet *return_reg;
103+
int coerce_error;
103104

104105
/* The global registry for c functions. Used to store meta-data
105106
* along with otherwise bare c function pointers. */

src/core/vm.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,10 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
13731373

13741374
/* Run vm */
13751375
janet_vm.fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
1376+
int old_coerce_error = janet_vm.coerce_error;
1377+
janet_vm.coerce_error = 1;
13761378
JanetSignal signal = run_vm(janet_vm.fiber, janet_wrap_nil());
1379+
janet_vm.coerce_error = old_coerce_error;
13771380

13781381
/* Teardown */
13791382
janet_vm.stackn = oldn;
@@ -1384,6 +1387,10 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
13841387
}
13851388

13861389
if (signal != JANET_SIGNAL_OK) {
1390+
/* Should match logic in janet_signalv */
1391+
if (signal != JANET_SIGNAL_ERROR) {
1392+
*janet_vm.return_reg = janet_wrap_string(janet_formatc("%v coerced from %s to error", *janet_vm.return_reg, janet_signal_names[signal]));
1393+
}
13871394
janet_panicv(*janet_vm.return_reg);
13881395
}
13891396

@@ -1430,8 +1437,10 @@ void janet_try_init(JanetTryState *state) {
14301437
state->vm_fiber = janet_vm.fiber;
14311438
state->vm_jmp_buf = janet_vm.signal_buf;
14321439
state->vm_return_reg = janet_vm.return_reg;
1440+
state->coerce_error = janet_vm.coerce_error;
14331441
janet_vm.return_reg = &(state->payload);
14341442
janet_vm.signal_buf = &(state->buf);
1443+
janet_vm.coerce_error = 0;
14351444
}
14361445

14371446
void janet_restore(JanetTryState *state) {
@@ -1440,6 +1449,7 @@ void janet_restore(JanetTryState *state) {
14401449
janet_vm.fiber = state->vm_fiber;
14411450
janet_vm.signal_buf = state->vm_jmp_buf;
14421451
janet_vm.return_reg = state->vm_return_reg;
1452+
janet_vm.coerce_error = state->coerce_error;
14431453
}
14441454

14451455
static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) {

src/include/janet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,7 @@ typedef struct {
12611261
/* new state */
12621262
jmp_buf buf;
12631263
Janet payload;
1264+
int coerce_error;
12641265
} JanetTryState;
12651266

12661267
/***** END SECTION TYPES *****/

test/suite-ev.janet

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,4 +465,13 @@
465465
# Close chat server
466466
(:close chat-server)
467467

468+
# Issue #1531
469+
(def c (ev/chan 0))
470+
(ev/spawn (while (def x (ev/take c))))
471+
(defn print-to-chan [x] (ev/give c x))
472+
(assert-error "coerce await inside janet_call to error"
473+
(with-dyns [*out* print-to-chan]
474+
(pp :foo)))
475+
(ev/chan-close c)
476+
468477
(end-suite)

0 commit comments

Comments
 (0)