Skip to content

Commit

Permalink
Fixed RegExp.prototype[@@replace]().
Browse files Browse the repository at this point in the history
With replacement containing "$'", "$\`" and Unicode characters.

The similar issue was fixed for String.prototype.replace() in
10127d70e941 (0.7.11).

Found by OSS-Fuzz.
  • Loading branch information
xeioex committed May 29, 2024
1 parent 8e7ce3b commit 532d583
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
27 changes: 12 additions & 15 deletions src/njs_regexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1461,8 +1462,8 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
}

i = 0;
pos = 0;
next_pos = 0;
p = s.start;
next = p;

while (i < results.items) {
r = njs_arr_item(&results, i++);
Expand Down Expand Up @@ -1491,13 +1492,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
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)) {
Expand Down Expand Up @@ -1578,15 +1573,17 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
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)) {
Expand All @@ -1599,8 +1596,8 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
}
}

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);
Expand Down
3 changes: 3 additions & 0 deletions src/test/njs_unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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("βα") },

Expand Down

0 comments on commit 532d583

Please sign in to comment.