aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorCalvin Rose <calsrose@gmail.com>2026-02-15 23:17:53 -0600
committerCalvin Rose <calsrose@gmail.com>2026-02-16 09:02:07 -0600
commit0299620a2d7b8e9d833a2c7ac5dc4135c9302f69 (patch)
treeec985f4a3ab82655a1be748decf5a997b30f7b6d
parentExpose module/add-syspath and update CHANGELOG.md (diff)
Code defensively with regard to stack resizes from custom get and put
for abstract types. Abstract types whose get/put/length/etc. implementations allocated fiber slots could break the VM by invalidating the stack pointer in the interpreter. This is admittedly a bit unusual but is something most users would probably expect to work. Debugging this would be a real pain.
-rw-r--r--src/core/value.c4
-rw-r--r--src/core/vm.c73
2 files changed, 59 insertions, 18 deletions
diff --git a/src/core/value.c b/src/core/value.c
index ae407f7c..2a0c4fe0 100644
--- a/src/core/value.c
+++ b/src/core/value.c
@@ -495,7 +495,7 @@ Janet janet_in(Janet ds, Janet key) {
if (!(type->get)(janet_unwrap_abstract(ds), key, &value))
janet_panicf("key %v not found in %v ", key, ds);
} else {
- janet_panicf("no getter for %v ", ds);
+ janet_panicf("no getter for %v", ds);
}
break;
}
@@ -622,7 +622,7 @@ Janet janet_getindex(Janet ds, int32_t index) {
if (!(type->get)(janet_unwrap_abstract(ds), janet_wrap_integer(index), &value))
value = janet_wrap_nil();
} else {
- janet_panicf("no getter for %v ", ds);
+ janet_panicf("no getter for %v", ds);
}
break;
}
diff --git a/src/core/vm.c b/src/core/vm.c
index 0d19aea7..02ee3d10 100644
--- a/src/core/vm.c
+++ b/src/core/vm.c
@@ -129,7 +129,9 @@
if (!janet_checktype(op1, JANET_NUMBER)) {\
vm_commit();\
Janet _argv[2] = { op1, janet_wrap_number(CS) };\
- stack[A] = janet_mcall(#op, 2, _argv);\
+ Janet a = janet_mcall(#op, 2, _argv);\
+ stack = fiber->data + fiber->frame;\
+ stack[A] = a;\
vm_checkgc_pcnext();\
} else {\
double x1 = janet_unwrap_number(op1);\
@@ -143,7 +145,9 @@
if (!janet_checktype(op1, JANET_NUMBER)) {\
vm_commit();\
Janet _argv[2] = { op1, janet_wrap_number(CS) };\
- stack[A] = janet_mcall(#op, 2, _argv);\
+ Janet a = janet_mcall(#op, 2, _argv);\
+ stack = fiber->data + fiber->frame;\
+ stack[A] = a;\
vm_checkgc_pcnext();\
} else {\
double y1 = janet_unwrap_number(op1);\
@@ -166,7 +170,9 @@
vm_pcnext();\
} else {\
vm_commit();\
- stack[A] = janet_binop_call(#op, "r" #op, op1, op2);\
+ Janet a = janet_binop_call(#op, "r" #op, op1, op2);\
+ stack = fiber->data + fiber->frame;\
+ stack[A] = a;\
vm_checkgc_pcnext();\
}\
}
@@ -186,7 +192,9 @@
vm_pcnext();\
} else {\
vm_commit();\
- stack[A] = janet_binop_call(#op, "r" #op, op1, op2);\
+ Janet a = janet_binop_call(#op, "r" #op, op1, op2);\
+ stack = fiber->data + fiber->frame;\
+ stack[A] = a;\
vm_checkgc_pcnext();\
}\
}
@@ -203,7 +211,9 @@
vm_pcnext();\
} else {\
vm_commit();\
- stack[A] = janet_wrap_boolean(janet_compare(op1, op2) op 0);\
+ Janet a = janet_wrap_boolean(janet_compare(op1, op2) op 0);\
+ stack = fiber->data + fiber->frame;\
+ stack[A] = a;\
vm_checkgc_pcnext();\
}\
}
@@ -217,7 +227,9 @@
vm_pcnext();\
} else {\
vm_commit();\
- stack[A] = janet_wrap_boolean(janet_compare(op1, janet_wrap_integer(CS)) op 0);\
+ Janet a = janet_wrap_boolean(janet_compare(op1, janet_wrap_integer(CS)) op 0);\
+ stack = fiber->data + fiber->frame;\
+ stack[A] = a;\
vm_checkgc_pcnext();\
}\
}
@@ -710,7 +722,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_pcnext();
} else {
vm_commit();
- stack[A] = janet_binop_call("div", "rdiv", op1, op2);
+ Janet a = janet_binop_call("div", "rdiv", op1, op2);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
vm_checkgc_pcnext();
}
}
@@ -730,7 +744,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_pcnext();
} else {
vm_commit();
- stack[A] = janet_binop_call("mod", "rmod", op1, op2);
+ Janet a = janet_binop_call("mod", "rmod", op1, op2);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
vm_checkgc_pcnext();
}
}
@@ -745,7 +761,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_pcnext();
} else {
vm_commit();
- stack[A] = janet_binop_call("%", "r%", op1, op2);
+ Janet a = janet_binop_call("%", "r%", op1, op2);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
vm_checkgc_pcnext();
}
}
@@ -766,7 +784,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_pcnext();
} else {
vm_commit();
- stack[A] = janet_unary_call("~", op);
+ Janet a = janet_unary_call("~", op);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
vm_checkgc_pcnext();
}
}
@@ -872,8 +892,11 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
stack[A] = janet_wrap_boolean(!janet_checktype(stack[B], JANET_NUMBER) || (janet_unwrap_number(stack[B]) != (double) CS));
vm_pcnext();
- VM_OP(JOP_COMPARE)
- stack[A] = janet_wrap_integer(janet_compare(stack[B], stack[C]));
+ VM_OP(JOP_COMPARE) {
+ Janet a = janet_wrap_integer(janet_compare(stack[B], stack[C]));
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
+ }
vm_pcnext();
VM_OP(JOP_NEXT)
@@ -1157,6 +1180,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_commit();
fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL;
janet_put(stack[A], stack[B], stack[C]);
+ stack = fiber->data + fiber->frame;
fiber->flags &= ~JANET_FIBER_RESUME_NO_USEVAL;
vm_checkgc_pcnext();
@@ -1164,27 +1188,44 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
vm_commit();
fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL;
janet_putindex(stack[A], C, stack[B]);
+ stack = fiber->data + fiber->frame;
fiber->flags &= ~JANET_FIBER_RESUME_NO_USEVAL;
vm_checkgc_pcnext();
VM_OP(JOP_IN)
vm_commit();
- stack[A] = janet_in(stack[B], stack[C]);
+ {
+ Janet a = janet_in(stack[B], stack[C]);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
+ }
vm_pcnext();
VM_OP(JOP_GET)
vm_commit();
- stack[A] = janet_get(stack[B], stack[C]);
+ {
+ Janet a = janet_get(stack[B], stack[C]);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
+ }
vm_pcnext();
VM_OP(JOP_GET_INDEX)
vm_commit();
- stack[A] = janet_getindex(stack[B], C);
+ {
+ Janet a = janet_getindex(stack[B], C);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
+ }
vm_pcnext();
VM_OP(JOP_LENGTH)
vm_commit();
- stack[A] = janet_lengthv(stack[E]);
+ {
+ Janet a = janet_lengthv(stack[E]);
+ stack = fiber->data + fiber->frame;
+ stack[A] = a;
+ }
vm_pcnext();
VM_OP(JOP_MAKE_ARRAY) {