[njs] Fixed RegExp.prototype[@@replace]().

Vadim Zhestikov v.zhestikov at f5.com
Thu Feb 2 18:04:10 UTC 2023


details:   https://hg.nginx.org/njs/rev/286675dcfbc5
branches:  
changeset: 2037:286675dcfbc5
user:      Vadim Zhestikov <v.zhestikov at f5.com>
date:      Thu Feb 02 10:01:26 2023 -0800
description:
Fixed RegExp.prototype[@@replace]().

Previously, when RegExpExec() returned a fast-array with gaps
String.prototype.replace() might return erroneous exception
TypeError: Cannot convert object to primitive value.

diffstat:

 src/njs_regexp.c         |   4 ++++
 src/test/njs_unit_test.c |  42 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 42 insertions(+), 4 deletions(-)

diffs (79 lines):

diff -r 0f7aedb08056 -r 286675dcfbc5 src/njs_regexp.c
--- a/src/njs_regexp.c	Wed Feb 01 19:06:22 2023 -0800
+++ b/src/njs_regexp.c	Thu Feb 02 10:01:26 2023 -0800
@@ -1288,6 +1288,10 @@ njs_regexp_prototype_symbol_replace(njs_
         if (njs_fast_path(njs_is_fast_array(r) && njs_array_len(r) != 0)) {
             value = njs_array_start(r)[0];
 
+            if (!njs_is_valid(&value)) {
+                njs_set_undefined(&value);
+            }
+
         } else {
             ret = njs_value_property_i64(vm, r, 0, &value);
             if (njs_slow_path(ret == NJS_ERROR)) {
diff -r 0f7aedb08056 -r 286675dcfbc5 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Feb 01 19:06:22 2023 -0800
+++ b/src/test/njs_unit_test.c	Thu Feb 02 10:01:26 2023 -0800
@@ -9063,8 +9063,19 @@ static njs_unit_test_t  njs_test[] =
               "re.exec = function () {"
               "    return a;"
               "};"
-              "var r = 'any_string'.replace(re);"),
-      njs_str("undefined") },
+              "'any_string'.replace(re)"),
+      njs_str("undefinedg") },
+
+    { njs_str("var cnt = 0;"
+              "var a = [];"
+              "a[2] = '';"
+              "var re = /any_regexp/g;"
+              "re.exec = function () {"
+              "    if (cnt++ > 1) return null;"
+              "    return a;"
+              "};"
+              "'any_string'.replace(re)"),
+      njs_str("undefinedg") },
 
     { njs_str("var a = [];"
               "a[2] = {toString() {a[2**20] = 1; return 'X';}}; "
@@ -9077,14 +9088,37 @@ static njs_unit_test_t  njs_test[] =
               "'abc'.replace(re, '@$1|$2|$3|$4|$99|$100|@')"),
       njs_str("@|X||Y|Z|0|@") },
 
+    { njs_str("var cnt = 0;"
+              "var a = [];"
+              "a[2] = {toString() {a[2**20] = 1; return 'X';}}; "
+              "a[4] = 'Y';"
+              "a[99] = 'Z';"
+              "a[100] = '*';"
+              "a[200] = '!';"
+              "var re = /b/g;"
+              "re.exec = () => {if (cnt++ > 1) return null; return a};"
+              "'abc'.replace(re, '@$1|$2|$3|$4|$99|$100|@')"),
+      njs_str("@|X||Y|Z|0|@") },
+
     { njs_str("var a = [];"
               "Object.defineProperty(a, 32768, {});"
               "var re = /any_regexp/;"
               "re.exec = function () {"
               "    return a;"
               "};"
-              "var r = 'any_string'.replace(re);"),
-      njs_str("undefined") },
+              "'any_string'.replace(re)"),
+      njs_str("undefinedg") },
+
+    { njs_str("var cnt = 0;"
+              "var a = [];"
+              "Object.defineProperty(a, 32768, {});"
+              "var re = /any_regexp/g;"
+              "re.exec = function () {"
+              "    if (cnt++ > 1) return null;"
+              "    return a;"
+              "};"
+              "'any_string'.replace(re)"),
+      njs_str("undefinedg") },
 
     { njs_str("/=/"),
       njs_str("/=/") },


More information about the nginx-devel mailing list