]> git.kaiwu.me - njs.git/commitdiff
Fixed regexp literals parsing.
authorAlexander Borisov <alexander.borisov@nginx.com>
Wed, 15 May 2019 09:51:31 +0000 (12:51 +0300)
committerAlexander Borisov <alexander.borisov@nginx.com>
Wed, 15 May 2019 09:51:31 +0000 (12:51 +0300)
Problems were observed:
1. Escaping symbols: /\\\\/
2. Solidus symbol ('/') in square bracket: /[/]/

This closes #149 issue on GitHub.

njs/njs_regexp.c
njs/test/njs_unit_test.c

index bc1544ce7bc7b4146e2924fc5b534f5658dd3100..19c7ae758b2f3dde7f721dae419b204b88453976 100644 (file)
@@ -209,7 +209,7 @@ njs_regexp_create(njs_vm_t *vm, njs_value_t *value, u_char *start,
 njs_token_t
 njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value)
 {
-    u_char                *p, c;
+    u_char                *p;
     nxt_str_t             text;
     njs_lexer_t           *lexer;
     njs_regexp_flags_t    flags;
@@ -219,13 +219,37 @@ njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value)
 
     for (p = lexer->start; p < lexer->end; p++) {
 
-        c = *p;
+        switch (*p) {
+        case '\n':
+        case '\r':
+            goto failed;
+
+        case '[':
+            while (++p < lexer->end && *p != ']') {
+                switch (*p) {
+                case '\n':
+                case '\r':
+                    goto failed;
+
+                case '\\':
+                    if (++p < lexer->end && (*p == '\n' || *p == '\r')) {
+                        goto failed;
+                    }
+
+                    break;
+                }
+            }
 
-        if (c == '\n' || c == '\r') {
             break;
-        }
 
-        if (c == '/' && !(p > lexer->start && p[-1] == '\\')) {
+        case '\\':
+            if (++p < lexer->end && (*p == '\n' || *p == '\r')) {
+                goto failed;
+            }
+
+            break;
+
+        case '/':
             text.start = lexer->start;
             text.length = p - text.start;
             p++;
@@ -255,6 +279,8 @@ njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value)
         }
     }
 
+failed:
+
     njs_parser_syntax_error(vm, parser, "Unterminated RegExp \"%*s\"",
                             p - (lexer->start - 1), lexer->start - 1);
 
index 8730f8a7516cf478fea316ec9f004ded23946b88..02bc3c1660d956e9dbff2b39e0f84bde785eeb38 100644 (file)
@@ -7073,6 +7073,37 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("/a\\q/"),
       nxt_string("/a\\q/") },
 
+    { nxt_string("/\\\\/"),
+      nxt_string("/\\\\/") },
+
+    { nxt_string("/\\\\\\/"),
+      nxt_string("SyntaxError: Unterminated RegExp \"/\\\\\\/\" in 1") },
+
+    { nxt_string("/\\\\\\\\/"),
+      nxt_string("/\\\\\\\\/") },
+
+    { nxt_string("/\\\\\\//"),
+      nxt_string("/\\\\\\//") },
+
+    { nxt_string("/[A-Z/]/"),
+      nxt_string("/[A-Z/]/") },
+
+    { nxt_string("/[A-Z\n]/"),
+      nxt_string("SyntaxError: Unterminated RegExp \"/[A-Z\" in 1") },
+
+    { nxt_string("/[A-Z\\\n]/"),
+      nxt_string("SyntaxError: Unterminated RegExp \"/[A-Z\\\" in 1") },
+
+    { nxt_string("/\\\n/"),
+      nxt_string("SyntaxError: Unterminated RegExp \"/\\\" in 1") },
+
+    { nxt_string("/^[A-Za-z0-9+/]{4}$/.test('////')"),
+      nxt_string("true") },
+
+    { nxt_string("'[]!\"#$%&\\'()*+,.\\/:;<=>?@\\^_`{|}-'.split('')"
+                 ".every(ch=>/[\\]\\[!\"#$%&'()*+,.\\/:;<=>?@\\^_`{|}-]/.test(ch))"),
+      nxt_string("true") },
+
     { nxt_string("/a\\q/.test('a\\q')"),
       nxt_string("true") },