[njs] Parser: correctly fixing closing brace unwinding for invalid syntax.

Alexander Borisov alexander.borisov at nginx.com
Sat Jun 6 15:16:27 UTC 2020


details:   https://hg.nginx.org/njs/rev/857c2166d10b
branches:  
changeset: 1427:857c2166d10b
user:      Alexander Borisov <alexander.borisov at nginx.com>
date:      Sat Jun 06 18:15:07 2020 +0300
description:
Parser: correctly fixing closing brace unwinding for invalid syntax.

The issue was introduced in 86f55a7dc4a4.

Previous attempts to catch unprocessed token in ea1754b79e7a and 61dce54ce3d5
were misplaced.

diffstat:

 src/njs_parser.c         |   78 ++++++++++-----------------------
 src/test/njs_unit_test.c |  108 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 53 deletions(-)

diffs (367 lines):

diff -r bc79f5c80452 -r 857c2166d10b src/njs_parser.c
--- a/src/njs_parser.c	Thu Jun 04 17:26:01 2020 +0300
+++ b/src/njs_parser.c	Sat Jun 06 18:15:07 2020 +0300
@@ -1154,7 +1154,7 @@ njs_parser_primary_expression_test(njs_p
 
         njs_parser_next(parser, njs_parser_expression);
 
-        return njs_parser_after(parser, current, NULL, 1,
+        return njs_parser_after(parser, current, NULL, 0,
                                 njs_parser_close_parenthesis);
 
     default:
@@ -3137,10 +3137,6 @@ njs_parser_expression_node(njs_parser_t 
 {
     njs_parser_node_t  *node;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3163,7 +3159,7 @@ njs_parser_expression_node(njs_parser_t 
 
     njs_lexer_consume_token(parser->lexer, 1);
 
-    return njs_parser_after(parser, current, node, 0, after);
+    return njs_parser_after(parser, current, node, 1, after);
 }
 
 
@@ -3204,7 +3200,7 @@ njs_parser_update_expression(njs_parser_
     njs_lexer_consume_token(parser->lexer, 1);
     njs_parser_next(parser, njs_parser_left_hand_side_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_update_expression_unary);
 }
 
@@ -3267,10 +3263,6 @@ static njs_int_t
 njs_parser_update_expression_unary(njs_parser_t *parser,
     njs_lexer_token_t *token, njs_queue_link_t *current)
 {
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (!njs_parser_is_lvalue(parser->node)) {
         njs_parser_ref_error(parser,
                              "Invalid left-hand side in prefix operation");
@@ -3354,7 +3346,7 @@ njs_parser_unary_expression(njs_parser_t
 
     njs_lexer_consume_token(parser->lexer, 1);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_unary_expression_next);
 }
 
@@ -3382,10 +3374,6 @@ njs_parser_unary_expression_next(njs_par
     njs_token_type_t   type;
     njs_parser_node_t  *node;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     type = parser->target->token_type;
     node = parser->node;
 
@@ -3464,10 +3452,6 @@ njs_parser_exponentiation_expression_mat
 {
     njs_parser_node_t  *node;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3494,7 +3478,7 @@ njs_parser_exponentiation_expression_mat
 
     njs_parser_next(parser, njs_parser_exponentiation_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_exponentiation_expression_match);
 }
 
@@ -3520,10 +3504,6 @@ njs_parser_multiplicative_expression_mat
     njs_parser_node_t       *node;
     njs_vmcode_operation_t  operation;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3561,7 +3541,7 @@ njs_parser_multiplicative_expression_mat
 
     njs_parser_next(parser, njs_parser_exponentiation_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_multiplicative_expression_match);
 }
 
@@ -3587,10 +3567,6 @@ njs_parser_additive_expression_match(njs
     njs_parser_node_t       *node;
     njs_vmcode_operation_t  operation;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3624,7 +3600,7 @@ njs_parser_additive_expression_match(njs
 
     njs_parser_next(parser, njs_parser_multiplicative_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_additive_expression_match);
 }
 
@@ -3650,10 +3626,6 @@ njs_parser_shift_expression_match(njs_pa
     njs_parser_node_t       *node;
     njs_vmcode_operation_t  operation;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3691,7 +3663,7 @@ njs_parser_shift_expression_match(njs_pa
 
     njs_parser_next(parser, njs_parser_additive_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_shift_expression_match);
 }
 
@@ -3717,10 +3689,6 @@ njs_parser_relational_expression_match(n
     njs_parser_node_t       *node;
     njs_vmcode_operation_t  operation;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3770,7 +3738,7 @@ njs_parser_relational_expression_match(n
 
     njs_parser_next(parser, njs_parser_shift_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_relational_expression_match);
 }
 
@@ -3796,10 +3764,6 @@ njs_parser_equality_expression_match(njs
     njs_parser_node_t       *node;
     njs_vmcode_operation_t  operation;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     if (parser->target != NULL) {
         parser->target->right = parser->node;
         parser->target->right->dest = parser->target;
@@ -3841,7 +3805,7 @@ njs_parser_equality_expression_match(njs
 
     njs_parser_next(parser, njs_parser_relational_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_equality_expression_match);
 }
 
@@ -3979,10 +3943,6 @@ njs_parser_coalesce_expression(njs_parse
     njs_token_type_t   type;
     njs_parser_node_t  *node;
 
-    if (parser->ret != NJS_OK) {
-        return njs_parser_failed(parser);
-    }
-
     node = parser->node;
 
     if (parser->target != NULL) {
@@ -4016,7 +3976,7 @@ njs_parser_coalesce_expression(njs_parse
     njs_lexer_consume_token(parser->lexer, 1);
     njs_parser_next(parser, njs_parser_bitwise_OR_expression);
 
-    return njs_parser_after(parser, current, node, 0,
+    return njs_parser_after(parser, current, node, 1,
                             njs_parser_coalesce_expression);
 }
 
@@ -4657,7 +4617,7 @@ njs_parser_block_statement(njs_parser_t 
 
     njs_parser_next(parser, njs_parser_statement_list);
 
-    return njs_parser_after(parser, current, target, 1,
+    return njs_parser_after(parser, current, target, 0,
                             njs_parser_block_statement_close_brace);
 }
 
@@ -4689,6 +4649,10 @@ njs_parser_block_statement_close_brace(n
 {
     njs_parser_node_t  *node;
 
+    if (parser->ret != NJS_OK) {
+        return njs_parser_failed(parser);
+    }
+
     if (token->type != NJS_TOKEN_CLOSE_BRACE) {
         return njs_parser_failed(parser);
     }
@@ -4728,7 +4692,15 @@ njs_parser_statement_list_next(njs_parse
     njs_queue_link_t *current)
 {
     if (parser->ret != NJS_OK) {
-        parser->node = parser->target;
+        if (token->type != NJS_TOKEN_CLOSE_BRACE) {
+            parser->node = parser->target;
+            return njs_parser_stack_pop(parser);
+        }
+
+        return njs_parser_failed(parser);
+    }
+
+    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
         return njs_parser_stack_pop(parser);
     }
 
diff -r bc79f5c80452 -r 857c2166d10b src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Thu Jun 04 17:26:01 2020 +0300
+++ b/src/test/njs_unit_test.c	Sat Jun 06 18:15:07 2020 +0300
@@ -16861,6 +16861,114 @@ static njs_unit_test_t  njs_test[] =
 
     { njs_str("{{}{1>>}"),
       njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}{r=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}{var a = }"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}T=>}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a = b +}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a = b -}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a = b *}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a = b /}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a = b %}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a = b++}"),
+      njs_str("ReferenceError: \"a\" is not defined in 1") },
+
+    { njs_str("{{}a = b--}"),
+      njs_str("ReferenceError: \"a\" is not defined in 1") },
+
+    { njs_str("{{}a =}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a +=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a -=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a *=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a /=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a %=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a ===}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a ==}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a !=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a !==}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a >}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a <}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a <=}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a &&}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a ||}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a ??}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a &}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a |}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a ^}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a <<}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}a >>}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}new}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}delete}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}void}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{}typeof}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("{{} ({a: 1, b: {}\n}\n})\n}"),
+      njs_str("SyntaxError: Unexpected token \"}\" in 3") },
 };
 
 


More information about the nginx-devel mailing list