diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-02-11 23:44:29 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-02-11 23:46:26 +0100 |
commit | a29bad9454edcc285f7f37410b6822affede44d1 (patch) | |
tree | 1f0f2255cc64bfcc84efeab0ed5ae07f4f589b24 | |
parent | 86f0662f891ac83f474a412b4271af996f1ea44e (diff) |
compiler: fix patchlist corruption on switch statement syntax errors
When compiling a switch statement with duplicate `default` cases or a switch
statement with syntax errors before the body block, two error handling cases
were hit in the code that prematurely returned from the function without
resetting the compiler's patchlist pointer away from the on-stack patchlist
that had been set up for the switch statement.
Upon processing a subsequent break or continue control statement, a realloc
was performed on the then invalid patchlist contents, triggering a
segmentation fault or libc assert.
Solve this issue by not returning from the function but breaking the switch
body parsing loop.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | compiler.c | 4 | ||||
-rw-r--r-- | tests/custom/04_bugs/32_compiler_switch_patchlist_corruption | 75 |
2 files changed, 77 insertions, 2 deletions
@@ -2448,7 +2448,7 @@ uc_compiler_compile_switch(uc_compiler_t *compiler) uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, "more than one switch default case"); - return; + break; } uc_compiler_parse_consume(compiler, TK_COLON); @@ -2511,7 +2511,7 @@ uc_compiler_compile_switch(uc_compiler_t *compiler) uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting 'case' or 'default'"); - return; + break; } } diff --git a/tests/custom/04_bugs/32_compiler_switch_patchlist_corruption b/tests/custom/04_bugs/32_compiler_switch_patchlist_corruption new file mode 100644 index 0000000..d256de5 --- /dev/null +++ b/tests/custom/04_bugs/32_compiler_switch_patchlist_corruption @@ -0,0 +1,75 @@ +When compiling a switch statement with duplicate `default` cases or a switch +statement with syntax errors before the body block, two error handling cases +were hit in the code that prematurely returned from the function without +resetting the compiler's patchlist pointer away from the on-stack patchlist +that had been set up for the switch statement. + +Upon processing a subsequent break or continue control statement, a realloc +was performed on the then invalid patchlist contents, triggering a +segmentation fault or libc assert. + +-- Testcase -- +{% + switch (1) { + default: break; + default: break; + } +%} +-- End -- + +-- Expect stderr -- +Syntax error: more than one switch default case +In line 4, byte 3: + + ` default: break;` + ^-- Near here + + +Syntax error: break must be inside loop or switch +In line 4, byte 12: + + ` default: break;` + Near here -------^ + + +Syntax error: Expecting expression +In line 5, byte 2: + + ` }` + ^-- Near here + + +-- End -- + + +-- Testcase -- +{% + switch (*) { + break; + } +%} +-- End -- + +-- Expect stderr -- +Syntax error: Expecting expression +In line 2, byte 10: + + ` switch (*) {` + Near here --^ + + +Syntax error: break must be inside loop or switch +In line 3, byte 3: + + ` break;` + ^-- Near here + + +Syntax error: Expecting expression +In line 4, byte 2: + + ` }` + ^-- Near here + + +-- End -- |