summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-02-11 23:44:29 +0100
committerJo-Philipp Wich <jo@mein.io>2022-02-11 23:46:26 +0100
commita29bad9454edcc285f7f37410b6822affede44d1 (patch)
tree1f0f2255cc64bfcc84efeab0ed5ae07f4f589b24
parent86f0662f891ac83f474a412b4271af996f1ea44e (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.c4
-rw-r--r--tests/custom/04_bugs/32_compiler_switch_patchlist_corruption75
2 files changed, 77 insertions, 2 deletions
diff --git a/compiler.c b/compiler.c
index f69ee2d..00f9f11 100644
--- a/compiler.c
+++ b/compiler.c
@@ -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 --