diff options
-rw-r--r-- | compiler.c | 4 | ||||
-rw-r--r-- | tests/03_bugs/12_altblock_stack_mismatch | 26 |
2 files changed, 30 insertions, 0 deletions
@@ -1867,12 +1867,16 @@ uc_compiler_compile_local(uc_compiler *compiler) static uc_tokentype_t uc_compiler_compile_altifblock(uc_compiler *compiler) { + uc_compiler_enter_scope(compiler); + while (true) { switch (compiler->parser->curr.type) { case TK_ELIF: case TK_ELSE: case TK_ENDIF: case TK_EOF: + uc_compiler_leave_scope(compiler); + return compiler->parser->curr.type; default: diff --git a/tests/03_bugs/12_altblock_stack_mismatch b/tests/03_bugs/12_altblock_stack_mismatch new file mode 100644 index 0000000..6805888 --- /dev/null +++ b/tests/03_bugs/12_altblock_stack_mismatch @@ -0,0 +1,26 @@ +When compiling alternative syntax blocks, such as `for ...: endfor`, +`if ...: endif` etc., the compiler didn't assign the contained statements +to a dedicated lexical scope, which caused a stack mismatch between +compiler and vm when such blocks declaring local variables weren't +actually executed. + +-- Expect stdout -- +2 +-- End -- + +-- Testcase -- +{% + if (false): + let a = 1; + endif; + + /* Due to lack of own lexical scope above, the compiler assumed + * that `a` is still on stack but the code to initialize it was + * never executed, so stack offsets were shifted by one from here + * on throughout the rest of the program. */ + + let b = 2; + + print(b, "\n"); +%} +-- End -- |