[njs] Fixed RegExpBuiltinExec() with global flag and byte-strings.

Dmitry Volyntsev xeioex at nginx.com
Tue Sep 1 17:32:51 UTC 2020


details:   https://hg.nginx.org/njs/rev/e03701b6e8aa
branches:  
changeset: 1514:e03701b6e8aa
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Sep 01 17:25:33 2020 +0000
description:
Fixed RegExpBuiltinExec() with global flag and byte-strings.

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.

diffstat:

 src/njs_regexp.c         |  20 +++++++++++++++++---
 src/test/njs_unit_test.c |  14 ++++++++++++--
 2 files changed, 29 insertions(+), 5 deletions(-)

diffs (70 lines):

diff -r d00a6ec5a39a -r e03701b6e8aa src/njs_regexp.c
--- a/src/njs_regexp.c	Tue Sep 01 16:37:33 2020 +0000
+++ b/src/njs_regexp.c	Tue Sep 01 17:25:33 2020 +0000
@@ -929,6 +929,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
     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
         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;
diff -r d00a6ec5a39a -r e03701b6e8aa src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Tue Sep 01 16:37:33 2020 +0000
+++ b/src/test/njs_unit_test.c	Tue Sep 01 17:25:33 2020 +0000
@@ -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)"),


More information about the nginx-devel mailing list