Skip to content

Instantly share code, notes, and snippets.

@H2CO3
Created November 24, 2014 08:08
Show Gist options
  • Save H2CO3/306cbd9df9e08ced5361 to your computer and use it in GitHub Desktop.
Save H2CO3/306cbd9df9e08ced5361 to your computer and use it in GitHub Desktop.
[BUGFIX] – Sparkling parser crashes
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.
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