diff options
-rw-r--r-- | compiler.c | 3 | ||||
-rw-r--r-- | tests/custom/99_bugs/45_compiler_loop_ctrl_unclosed_upvals | 22 |
2 files changed, 24 insertions, 1 deletions
@@ -2969,7 +2969,8 @@ uc_compiler_compile_control(uc_compiler_t *compiler) /* pop locals in all scopes covered by the target patchlist */ for (i = locals->count; i > 0 && (size_t)locals->entries[i - 1].depth > p->depth; i--) - uc_compiler_emit_insn(compiler, 0, I_POP); + uc_compiler_emit_insn(compiler, 0, + locals->entries[i - 1].captured ? I_CUPV : I_POP); uc_vector_grow(p); diff --git a/tests/custom/99_bugs/45_compiler_loop_ctrl_unclosed_upvals b/tests/custom/99_bugs/45_compiler_loop_ctrl_unclosed_upvals new file mode 100644 index 0000000..d4b7ed8 --- /dev/null +++ b/tests/custom/99_bugs/45_compiler_loop_ctrl_unclosed_upvals @@ -0,0 +1,22 @@ +When compiling loop control statements, the compiler incorrectly emitted an +I_POP instead of an I_CUPV instruction for open upvalues, causing closures to +reference unclosed upvalues that went out of scope, potentially leading to +invalid stack accesses in subsequent code. + +-- Testcase -- +{% + let dest; + + for (let i in [ 1 ]) { + let foo = i; + dest = () => print(foo, '\n'); + continue; + } + + dest(); +%} +-- End -- + +-- Expect stdout -- +1 +-- End -- |