diff options
author | Felix Fietkau <nbd@nbd.name> | 2024-02-08 20:46:02 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2024-02-13 17:03:55 +0100 |
commit | 3f9811d2f7b730f1f1d030872ae1def7e8349be6 (patch) | |
tree | 649af4c5bac5512ee0223d8fa4dd31dae5dd6cee | |
parent | dce19b7cce0bef3ec13166bcd85766cc8c0ecdba (diff) |
compiler: close upvalues on loop control statements
When removing locals from all scopes, upvalues need to be considered like
in uc_compiler_leave_scope(). Closing them is required to avoid leaving
lingering references to stack values that went out of scope, which would
lead to invalid memory accesses in subsequent code when such upvalues are
used by closures.
Fixes: #187
Signed-off-by: Felix Fietkau <nbd@nbd.name>
[add testcase, reword commit message]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-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 -- |