Found during the ouroboros#57 frontend work (F-OURO-22): OP_SET_LOCAL's handler guards if ((int)slot < e->count) (src/vm.c:2430) and the else path silently discards the value. The C compiler always pairs slot allocation with reservation (module chunks via the vm_run entry check, functions via the call-env sizing), so compiler-emitted bytecode never hits it — but hand-built bytecode (vm_run_bytecode descriptors, ouroboros codegen) does: a defaults prologue writing a parameter slot on an underfed call wrote into a nonexistent slot and the program continued with the variable unbound, no diagnostic. ouroboros currently works around it by padding a never-read local (__defaults_pad) to force env_reserve_slots.
Silent-drop family (#326/#327/#335-#337/#341 all shipped fixes for this shape). Options:
- Raise a runtime error (
SET_LOCAL slot N out of range) — honest, catches bad descriptors immediately; or
- Auto-reserve (
env_reserve_slots(e, slot+1)) — permissive, matches what the compiler's invariant produces anyway.
(1) fits the family better: out-of-range slots in hand-built bytecode are bugs, not requests. Either way the ouroboros pad workaround can then be dropped at the next EIGS_REF bump.
Test: a vm_run_bytecode descriptor with an OP_SET_LOCAL past the env size errors (or works) instead of silently no-oping.
Found during the ouroboros#57 frontend work (F-OURO-22):
OP_SET_LOCAL's handler guardsif ((int)slot < e->count)(src/vm.c:2430) and the else path silently discards the value. The C compiler always pairs slot allocation with reservation (module chunks via thevm_runentry check, functions via the call-env sizing), so compiler-emitted bytecode never hits it — but hand-built bytecode (vm_run_bytecodedescriptors, ouroboros codegen) does: a defaults prologue writing a parameter slot on an underfed call wrote into a nonexistent slot and the program continued with the variable unbound, no diagnostic. ouroboros currently works around it by padding a never-read local (__defaults_pad) to forceenv_reserve_slots.Silent-drop family (#326/#327/#335-#337/#341 all shipped fixes for this shape). Options:
SET_LOCAL slot N out of range) — honest, catches bad descriptors immediately; orenv_reserve_slots(e, slot+1)) — permissive, matches what the compiler's invariant produces anyway.(1) fits the family better: out-of-range slots in hand-built bytecode are bugs, not requests. Either way the ouroboros pad workaround can then be dropped at the next EIGS_REF bump.
Test: a
vm_run_bytecodedescriptor with anOP_SET_LOCALpast the env size errors (or works) instead of silently no-oping.