diff options
-rw-r--r-- | compiler.c | 16 | ||||
-rw-r--r-- | tests/custom/04_bugs/11_switch_stack_mismatch | 27 |
2 files changed, 42 insertions, 1 deletions
@@ -2475,7 +2475,7 @@ out: static void uc_compiler_compile_switch(uc_compiler_t *compiler) { - size_t i, test_jmp, skip_jmp, next_jmp, value_slot, default_off = 0; + size_t i, test_jmp, skip_jmp, next_jmp = 0, value_slot, default_off = 0; uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); uc_patchlist_t p = { .depth = compiler->scope_depth }; uc_locals_t *locals = &compiler->locals; @@ -2628,6 +2628,10 @@ uc_compiler_compile_switch(uc_compiler_t *compiler) /* jump to target */ uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[default_off + 2]); + + /* do not patch final match failure jump later, we handle it here + * in the default case */ + next_jmp = 0; } uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); @@ -2640,6 +2644,16 @@ uc_compiler_compile_switch(uc_compiler_t *compiler) uc_compiler_leave_scope(compiler); + /* if no default case exists, patch last case match failure jump */ + if (next_jmp) { + /* There's pop instructions for all local variables including the + * switch test value itself on the stack. Jump onto the last POP + * instruction (-1) to get rid of the on-stack switch test value + * but skip the POP instructions for all other scoped local variables + * which never have been initialized. */ + uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count - 1); + } + uc_compiler_backpatch(compiler, chunk->count, 0); } diff --git a/tests/custom/04_bugs/11_switch_stack_mismatch b/tests/custom/04_bugs/11_switch_stack_mismatch index cc3b41a..0cf82f0 100644 --- a/tests/custom/04_bugs/11_switch_stack_mismatch +++ b/tests/custom/04_bugs/11_switch_stack_mismatch @@ -37,3 +37,30 @@ Matching 3: } %} -- End -- + +-- Expect stdout -- +Matching 1: +Matching 2: + - 2: [ 3, 4 ] + - 3: [ 3, 4, 5, 6 ] +Matching 3: + - 3: [ null, null, 5, 6 ] +-- End -- + +-- Testcase -- +{% + for (let n in [1, 2, 3]) { + printf("Matching %d:\n", n); + + switch (n) { + case 2: + let a = 3, b = 4; + print(" - 2: ", [a, b], "\n"); + + case 3: + let c = 5, d = 6; + print(" - 3: ", [a, b, c, d], "\n"); + } + } +%} +-- End -- |