From 37de9d66c7a7a1b184a52f5a8fe6a0f700c351f8 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Tue, 1 Sep 2020 17:25:33 +0000 Subject: [PATCH] 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. --- src/njs_regexp.c | 20 +++++++++++++++++--- src/test/njs_unit_test.c | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/njs_regexp.c b/src/njs_regexp.c index 374610e4..657f3733 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -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(®exp->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(®exp->last_index, index); } lhq.key_hash = NJS_INDEX_HASH; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index b6efe042..94c81c5f 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -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)"), -- 2.47.3