]> git.kaiwu.me - njs.git/commitdiff
Fixed RegExpBuiltinExec() with global flag and byte-strings.
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 1 Sep 2020 17:25:33 +0000 (17:25 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Tue, 1 Sep 2020 17:25:33 +0000 (17:25 +0000)
The issue was introduced in f9082cd59ba6 (0.4.2).  Since 1c729f765cfb
(0.4.2) RegExp.prototype[Symbol.replace] with a regexp with the global
flag may result in an endless loop for byte-strings with broken UTF8
encoding.

src/njs_regexp.c
src/test/njs_unit_test.c

index 374610e45c15900b7a088c75f6764653af3f5c06..657f3733effad9c33f78464bde52976701b77e1c 100644 (file)
@@ -929,6 +929,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp,
     int                   *captures;
     u_char                *start;
     int32_t               size, length;
+    uint32_t              index;
     njs_int_t             ret;
     njs_uint_t            i, n;
     njs_array_t           *array;
@@ -982,11 +983,24 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp,
         goto fail;
     }
 
-    njs_set_number(&prop->value, njs_string_index(string, captures[0]));
+    if (type == NJS_REGEXP_UTF8) {
+        index = njs_string_index(string, captures[0]);
+
+    } else {
+        index = captures[0];
+    }
+
+    njs_set_number(&prop->value, index);
 
     if (pattern->global) {
-        njs_set_number(&regexp->last_index,
-                       njs_string_index(string, captures[1]));
+        if (type == NJS_REGEXP_UTF8) {
+            index = njs_string_index(string, captures[1]);
+
+        } else {
+            index = captures[1];
+        }
+
+        njs_set_number(&regexp->last_index, index);
     }
 
     lhq.key_hash = NJS_INDEX_HASH;
index b6efe042905218b2f5024e65cab37cdf2abc09e9..94c81c5f3fce3e8ed942fb84178efdba526d377a 100644 (file)
@@ -8307,6 +8307,12 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("RegExp.prototype[Symbol.replace].call(/b/, 'abc','B')"),
       njs_str("aBc") },
 
+    { njs_str("String.bytesFrom([253,242,141,10]).replace(/\\s/g, 'X')[3]"),
+      njs_str("X") },
+
+    { njs_str("String.bytesFrom([255,149,15,97,95]).replace(/_/g, 'X')[4]"),
+      njs_str("X") },
+
     { njs_str("/]/"),
       njs_str("/\\]/") },
 
@@ -10327,8 +10333,12 @@ static njs_unit_test_t  njs_test[] =
 #endif
 
     { njs_str("var r = /\\x80/g; r.exec('\\u0081\\u0080'.toBytes());"
-                 "r.lastIndex +' '+ r.source +' '+ r.source.length +' '+ r"),
-      njs_str("1 \\x80 4 /\\x80/g") },
+              "r.lastIndex +' '+ r.source +' '+ r.source.length +' '+ r"),
+      njs_str("2 \\x80 4 /\\x80/g") },
+
+    { njs_str("var r = /_/g; var index = r.exec(String.bytesFrom([255,149,15,97,95])).index;"
+              "[index, r.lastIndex]"),
+      njs_str("4,5") },
 
     { njs_str("var descs = Object.getOwnPropertyDescriptors(RegExp('a'));"
               "Object.keys(descs)"),