Created
November 24, 2014 08:08
-
-
Save H2CO3/306cbd9df9e08ced5361 to your computer and use it in GitHub Desktop.
[BUGFIX] – Sparkling parser crashes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is a diff for Sparkling @ commit 665e00d51dae99493958fb2e25fe5d56ffb66a15 | |
Fixes some crashes in the parser caused by infinite recursion upon encountering certain types of malformed Sparkling source. | |
Bugs found using `zzuf`, a fuzzing tool. | |
This is a patch and not a proper commit because I'm rewriting the parser in the meantime, and I don't want to deal with conflicts. They will be undone anyway – this patch is just a temporary (but nonehteless important) bugfix. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/parser.c b/src/parser.c | |
index 9cec3ce..32455b6 100644 | |
--- a/src/parser.c | |
+++ b/src/parser.c | |
@@ -149,6 +149,10 @@ SpnAST *spn_parser_parse_expression(SpnParser *p, const char *src) | |
init_parser(p, src); | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
+ | |
expr = parse_expr(p); | |
if (expr == NULL) { | |
@@ -318,11 +322,18 @@ static SpnAST *parse_function(SpnParser *p, int is_stmt) | |
/* skip identifier */ | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
} else { | |
/* optionally named function expression, lambda */ | |
if (p->curtok.tok == SPN_TOK_IDENT) { | |
name = stringvalue(&p->curtok.val); | |
spn_lex(p); | |
+ if (p->error) { | |
+ spn_object_release(name); | |
+ return NULL; | |
+ } | |
} else { | |
name = NULL; | |
} | |
@@ -808,6 +819,9 @@ static SpnAST *parse_term(SpnParser *p) | |
switch (p->curtok.tok) { | |
case SPN_TOK_LPAREN: | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
ast = parse_expr(p); | |
if (ast == NULL) { | |
@@ -897,11 +911,16 @@ static SpnAST *parse_term(SpnParser *p) | |
static SpnAST *parse_array_literal(SpnParser *p) | |
{ | |
- SpnAST *ast = spn_ast_new(SPN_NODE_ARRAY_LITERAL, p->lineno); | |
- SpnAST *tail = ast; | |
+ SpnAST *ast, *tail; | |
/* skip leading '[' */ | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
+ | |
+ ast = spn_ast_new(SPN_NODE_ARRAY_LITERAL, p->lineno); | |
+ tail = ast; | |
while (!spn_accept(p, SPN_TOK_RBRACKET)) { | |
/* parse value */ | |
@@ -942,11 +961,16 @@ static SpnAST *parse_array_literal(SpnParser *p) | |
static SpnAST *parse_hashmap_literal(SpnParser *p) | |
{ | |
- SpnAST *ast = spn_ast_new(SPN_NODE_HASHMAP_LITERAL, p->lineno); | |
- SpnAST *tail = ast; | |
+ SpnAST *ast, *tail; | |
/* skip '{' */ | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
+ | |
+ ast = spn_ast_new(SPN_NODE_HASHMAP_LITERAL, p->lineno); | |
+ tail = ast; | |
while (!spn_accept(p, SPN_TOK_RBRACE)) { | |
SpnAST *pair, *key, *val; | |
@@ -1439,6 +1463,9 @@ static SpnAST *parse_vardecl(SpnParser *p) | |
/* skip "var" keyword */ | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
do { | |
SpnString *name = stringvalue(&p->curtok.val); | |
@@ -1491,6 +1518,9 @@ static SpnAST *parse_const(SpnParser *p) | |
/* skip "const" or "global" keyword */ | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
do { | |
SpnString *name; | |
@@ -1503,7 +1533,11 @@ static SpnAST *parse_const(SpnParser *p) | |
} | |
name = stringvalue(&p->curtok.val); | |
+ | |
spn_lex(p); | |
+ if (p->error) { | |
+ return NULL; | |
+ } | |
if (!spn_accept(p, SPN_TOK_ASSIGN)) { | |
spn_parser_error(p, "expected `=' after identifier in const declaration", NULL); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment