[njs] Fixed RegExp.prototype[@@replace]().
noreply at nginx.com
noreply at nginx.com
Wed May 29 00:36:04 UTC 2024
details: https://hg.nginx.org/njs/rev/cb1baa3906f8
branches:
changeset: 2342:cb1baa3906f8
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue May 28 15:49:39 2024 -0700
description:
Fixed RegExp.prototype[@@replace]().
With replacement containing "$'", "$\`" and Unicode characters.
The similar issue was fixed for String.prototype.replace() in
10127d70e941 (0.7.11).
Found by OSS-Fuzz.
diffstat:
src/njs_regexp.c | 27 ++++++++++++---------------
src/test/njs_unit_test.c | 3 +++
2 files changed, 15 insertions(+), 15 deletions(-)
diffs (84 lines):
diff -r 29ffafd582a7 -r cb1baa3906f8 src/njs_regexp.c
--- a/src/njs_regexp.c Fri Apr 05 13:27:37 2024 -0700
+++ b/src/njs_regexp.c Tue May 28 15:49:39 2024 -0700
@@ -1330,7 +1330,8 @@ njs_int_t
njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval)
{
- int64_t n, last_index, ncaptures, pos, next_pos, length;
+ int64_t n, last_index, ncaptures, pos, length;
+ const u_char *p, *next;
njs_str_t rep, m;
njs_int_t ret;
njs_arr_t results;
@@ -1461,8 +1462,8 @@ njs_regexp_prototype_symbol_replace(njs_
}
i = 0;
- pos = 0;
- next_pos = 0;
+ p = s.start;
+ next = p;
while (i < results.items) {
r = njs_arr_item(&results, i++);
@@ -1491,13 +1492,7 @@ njs_regexp_prototype_symbol_replace(njs_
goto exception;
}
- if ((size_t) length != s.size) {
- /* UTF-8 string. */
- pos = njs_string_utf8_offset(s.start, s.start + s.size, pos)
- - s.start;
- }
-
- pos = njs_max(njs_min(pos, (int64_t) s.size), 0);
+ pos = njs_max(njs_min(pos, (int64_t) length), 0);
ret = njs_object_length(vm, r, &ncaptures);
if (njs_slow_path(ret != NJS_OK)) {
@@ -1578,15 +1573,17 @@ njs_regexp_prototype_symbol_replace(njs_
goto exception;
}
- if (pos >= next_pos) {
- njs_chb_append(&chain, &s.start[next_pos], pos - next_pos);
+ p = njs_string_offset(&s, pos);
+
+ if (p >= next) {
+ njs_chb_append(&chain, next, p - next);
njs_string_get(retval, &rep);
njs_chb_append_str(&chain, &rep);
njs_string_get(&matched, &m);
- next_pos = pos + (int64_t) m.length;
+ next = p + m.length;
}
if (!func_replace && njs_object_slots(r)) {
@@ -1599,8 +1596,8 @@ njs_regexp_prototype_symbol_replace(njs_
}
}
- if (next_pos < (int64_t) s.size) {
- njs_chb_append(&chain, &s.start[next_pos], s.size - next_pos);
+ if (next < s.start + s.size) {
+ njs_chb_append(&chain, next, s.start + s.size - next);
}
ret = njs_string_create_chb(vm, retval, &chain);
diff -r 29ffafd582a7 -r cb1baa3906f8 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Fri Apr 05 13:27:37 2024 -0700
+++ b/src/test/njs_unit_test.c Tue May 28 15:49:39 2024 -0700
@@ -9321,6 +9321,9 @@ static njs_unit_test_t njs_test[] =
{ njs_str("'ABCB'.replaceAll(/(?<b>B)/g, '|$<BB$$|>@')"),
njs_str("A|@C|@") },
+ { njs_str("'α'.repeat(8).replace(/()/g, '$`') == 'α'.repeat(44)"),
+ njs_str("true") },
+
{ njs_str("('β' + 'α'.repeat(33)+'β').replace(/(α+)(β+)/, (m, p1) => p1[32])"),
njs_str("βα") },
More information about the nginx-devel
mailing list