Skip to content

Commit 532d583

Browse files
committed
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.
1 parent 8e7ce3b commit 532d583

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

src/njs_regexp.c

+12-15
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,8 @@ njs_int_t
13301330
njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
13311331
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval)
13321332
{
1333-
int64_t n, last_index, ncaptures, pos, next_pos, length;
1333+
int64_t n, last_index, ncaptures, pos, length;
1334+
const u_char *p, *next;
13341335
njs_str_t rep, m;
13351336
njs_int_t ret;
13361337
njs_arr_t results;
@@ -1461,8 +1462,8 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
14611462
}
14621463

14631464
i = 0;
1464-
pos = 0;
1465-
next_pos = 0;
1465+
p = s.start;
1466+
next = p;
14661467

14671468
while (i < results.items) {
14681469
r = njs_arr_item(&results, i++);
@@ -1491,13 +1492,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
14911492
goto exception;
14921493
}
14931494

1494-
if ((size_t) length != s.size) {
1495-
/* UTF-8 string. */
1496-
pos = njs_string_utf8_offset(s.start, s.start + s.size, pos)
1497-
- s.start;
1498-
}
1499-
1500-
pos = njs_max(njs_min(pos, (int64_t) s.size), 0);
1495+
pos = njs_max(njs_min(pos, (int64_t) length), 0);
15011496

15021497
ret = njs_object_length(vm, r, &ncaptures);
15031498
if (njs_slow_path(ret != NJS_OK)) {
@@ -1578,15 +1573,17 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
15781573
goto exception;
15791574
}
15801575

1581-
if (pos >= next_pos) {
1582-
njs_chb_append(&chain, &s.start[next_pos], pos - next_pos);
1576+
p = njs_string_offset(&s, pos);
1577+
1578+
if (p >= next) {
1579+
njs_chb_append(&chain, next, p - next);
15831580

15841581
njs_string_get(retval, &rep);
15851582
njs_chb_append_str(&chain, &rep);
15861583

15871584
njs_string_get(&matched, &m);
15881585

1589-
next_pos = pos + (int64_t) m.length;
1586+
next = p + m.length;
15901587
}
15911588

15921589
if (!func_replace && njs_object_slots(r)) {
@@ -1599,8 +1596,8 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
15991596
}
16001597
}
16011598

1602-
if (next_pos < (int64_t) s.size) {
1603-
njs_chb_append(&chain, &s.start[next_pos], s.size - next_pos);
1599+
if (next < s.start + s.size) {
1600+
njs_chb_append(&chain, next, s.start + s.size - next);
16041601
}
16051602

16061603
ret = njs_string_create_chb(vm, retval, &chain);

src/test/njs_unit_test.c

+3
Original file line numberDiff line numberDiff line change
@@ -9321,6 +9321,9 @@ static njs_unit_test_t njs_test[] =
93219321
{ njs_str("'ABCB'.replaceAll(/(?<b>B)/g, '|$<BB$$|>@')"),
93229322
njs_str("A|@C|@") },
93239323

9324+
{ njs_str("'α'.repeat(8).replace(/()/g, '$`') == 'α'.repeat(44)"),
9325+
njs_str("true") },
9326+
93249327
{ njs_str("('β' + 'α'.repeat(33)+'β').replace(/(α+)(β+)/, (m, p1) => p1[32])"),
93259328
njs_str("βα") },
93269329

0 commit comments

Comments
 (0)