Raise a compile error on too many closures.

Previously, we had silent miscompiles in some cases.

The ideal fix is to let us reference upvalues beyond slot 255. One way
would be to add a new instruction pair that would reference a 16-bit
constant index, which would itself encode a pair of at least 16 bit
values instead of the current instruction which encodes a pair of 8 bit
values.
This commit is contained in:
Calvin Rose committed 2026-10-21 18:16:42 -05:00
1 parent 3606abc6d7
commit 2ff6b2cec0
3 files changed
+20

No files matched your search

+5
View File
@@ -414,6 +414,11 @@ found:
ret.envindex = -1;
return ret;
}
if (ret.index > 0xFF) {
janetc_error(c, janet_formatc("too many closure upvalues: %S", sym));
ret.envindex = -1;
return ret;
}
/* non-local scope needs to expose its environment */
JanetScope *original_scope = scope;
+7
View File
@@ -125,6 +125,10 @@ static void janetc_movenear(JanetCompiler *c,
JOP_GET_INDEX);
}
} else if (src.envindex >= 0) {
/* Convert src to near reg */
if (src.index > 255) {
janet_assert(0, "upvalue index > 255, cannot load");
}
janetc_emit(c,
((uint32_t)(src.index) << 24) |
((uint32_t)(src.envindex) << 16) |
@@ -158,6 +162,9 @@ static void janetc_moveback(JanetCompiler *c,
janetc_emit(c, JOP_MOVE_NEAR | ((uint32_t)(src) << 16) | ((uint32_t) newsrc << 8));
src = newsrc;
}
if (dest.index > 255) {
janet_assert(0, "upvalue index > 255, cannot store");
}
janetc_emit(c,
((uint32_t)(dest.index) << 24) |
((uint32_t)(dest.envindex) << 16) |
+8
View File
@@ -963,6 +963,10 @@ static JanetSlot janetc_while(JanetFopts opts, int32_t argn, const Janet *argv)
JanetFuncDef *def = janetc_pop_funcdef(c, janet_cstring("while"));
janet_def_addflags(def);
int32_t defindex = janetc_addfuncdef(c, def);
if (defindex > 255) {
janetc_error(c, janet_cstring("too many closures"));
return janetc_cslot(janet_wrap_nil());
}
/* Do basic optimization */
if (!(c->scope->flags & JANET_SCOPE_UNUSED)) {
janet_bytecode_optimize(def, c->optimize);
@@ -1212,6 +1216,10 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
janet_def_addflags(def);
defindex = janetc_addfuncdef(c, def);
if (defindex > 255) {
errmsg = "too many closures";
goto error;
}
/* Ensure enough slots for vararg function. */
if (arity + vararg > def->slotcount) def->slotcount = arity + vararg;