]> git.kaiwu.me - njs.git/commitdiff
Parser: fixed parsing of regexp flags.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 2 Jul 2020 12:58:50 +0000 (12:58 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 2 Jul 2020 12:58:50 +0000 (12:58 +0000)
src/njs_parser.c
src/njs_regexp.c
src/njs_regexp.h
src/test/njs_unit_test.c

index d022fcf1321f94dd4b6d2bc47d476c101167e151..89ab9bf99565ee41ebe01e57cf5a99985ae0cae8 100644 (file)
@@ -1247,7 +1247,7 @@ njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token,
             p++;
             lexer->start = p;
 
-            flags = njs_regexp_flags(&p, lexer->end, 0);
+            flags = njs_regexp_flags(&p, lexer->end);
 
             if (njs_slow_path(flags < 0)) {
                 njs_parser_syntax_error(parser, "Invalid RegExp flags \"%*s\"",
index 0960322792d5c23ad2ebf5b7058e97614e0556fb..05a0203179197fd08114d4cdd3c8e9f7c1964e58 100644 (file)
@@ -143,8 +143,10 @@ njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 
         start = string.start;
 
-        re_flags = njs_regexp_flags(&start, start + string.length, 1);
-        if (njs_slow_path(re_flags < 0)) {
+        re_flags = njs_regexp_flags(&start, start + string.length);
+        if (njs_slow_path(re_flags < 0
+                          || (size_t) (start - string.start) != string.length))
+        {
             njs_syntax_error(vm, "Invalid RegExp flags \"%V\"", &string);
             return NJS_ERROR;
         }
@@ -305,17 +307,15 @@ done:
 
 
 njs_regexp_flags_t
-njs_regexp_flags(u_char **start, u_char *end, njs_bool_t bound)
+njs_regexp_flags(u_char **start, u_char *end)
 {
     u_char              *p;
     njs_regexp_flags_t  flags, flag;
 
-    flags = 0;
+    flags = NJS_REGEXP_NO_FLAGS;
 
     for (p = *start; p < end; p++) {
-
         switch (*p) {
-
         case 'g':
             flag = NJS_REGEXP_GLOBAL;
             break;
@@ -328,24 +328,12 @@ njs_regexp_flags(u_char **start, u_char *end, njs_bool_t bound)
             flag = NJS_REGEXP_MULTILINE;
             break;
 
-        case ';':
-        case ' ':
-        case '\t':
-        case '\r':
-        case '\n':
-        case ',':
-        case ')':
-        case ']':
-        case '}':
-        case '.':
-            if (!bound) {
-                goto done;
+        default:
+            if (*p >= 'a' && *p <= 'z') {
+                goto invalid;
             }
 
-            /* Fall through. */
-
-        default:
-            goto invalid;
+            goto done;
         }
 
         if (njs_slow_path((flags & flag) != 0)) {
index d284e299f5c497bc678b1b45d79fe2cd9715fd96..500c6fa77d37dc7f58a66933537fe8d983470069 100644 (file)
@@ -10,6 +10,7 @@
 
 typedef enum {
     NJS_REGEXP_INVALID_FLAG = -1,
+    NJS_REGEXP_NO_FLAGS     =  0,
     NJS_REGEXP_GLOBAL       =  1,
     NJS_REGEXP_IGNORE_CASE  =  2,
     NJS_REGEXP_MULTILINE    =  4,
@@ -19,8 +20,7 @@ typedef enum {
 njs_int_t njs_regexp_init(njs_vm_t *vm);
 njs_int_t njs_regexp_create(njs_vm_t *vm, njs_value_t *value, u_char *start,
     size_t length, njs_regexp_flags_t flags);
-njs_regexp_flags_t njs_regexp_flags(u_char **start, u_char *end,
-    njs_bool_t bound);
+njs_regexp_flags_t njs_regexp_flags(u_char **start, u_char *end);
 njs_regexp_pattern_t *njs_regexp_pattern_create(njs_vm_t *vm,
     u_char *string, size_t length, njs_regexp_flags_t flags);
 njs_int_t njs_regexp_match(njs_vm_t *vm, njs_regex_t *regex,
index 3604d76e593c846a5bbf0a1702a5cd93eeab36c8..56c7c5f320c1bde0d5fd3bc780212b26b374f937 100644 (file)
@@ -9487,9 +9487,6 @@ static njs_unit_test_t  njs_test[] =
 
     /* RegExp. */
 
-    { njs_str("/./x"),
-      njs_str("SyntaxError: Invalid RegExp flags \"x\" in 1") },
-
     { njs_str("/"),
       njs_str("SyntaxError: Unterminated RegExp \"/\" in 1") },
 
@@ -9526,6 +9523,15 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("/\\\n/"),
       njs_str("SyntaxError: Unterminated RegExp \"/\\\" in 1") },
 
+    { njs_str("/./x"),
+      njs_str("SyntaxError: Invalid RegExp flags \"x\" in 1") },
+
+    { njs_str("/./.exec === RegExp.prototype.exec"),
+      njs_str("true") },
+
+    { njs_str("/./['exec'] === RegExp.prototype.exec"),
+      njs_str("true") },
+
     { njs_str("/^[A-Za-z0-9+/]{4}$/.test('////')"),
       njs_str("true") },
 
@@ -9736,6 +9742,15 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("new RegExp('', 'x')"),
       njs_str("SyntaxError: Invalid RegExp flags \"x\"") },
 
+    { njs_str("new RegExp('', 'g ')"),
+      njs_str("SyntaxError: Invalid RegExp flags \"g \"") },
+
+    { njs_str("new RegExp('', '')"),
+      njs_str("/(?:)/") },
+
+    { njs_str("new RegExp('', {toString:()=>'g'})"),
+      njs_str("/(?:)/g") },
+
     { njs_str("RegExp({})"),
       njs_str("/[object Object]/") },