Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/njs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

#include <njs_auto_config.h>

#define NJS_VERSION "1.0.1"
#define NJS_VERSION_NUMBER 0x010001
#define NJS_VERSION "1.0.2"
#define NJS_VERSION_NUMBER 0x010002


#include <string.h>
Expand Down
10 changes: 9 additions & 1 deletion src/njs_mp.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ njs_mp_alloc_large(njs_mp_t *mp, size_t alignment, size_t size)
u_char *p;
size_t aligned_size;
uint8_t type;
njs_bool_t discrete;
njs_mp_block_t *block;

/* Allocation must be less than 4G. */
Expand All @@ -600,7 +601,14 @@ njs_mp_alloc_large(njs_mp_t *mp, size_t alignment, size_t size)
size += size == 0;
#endif

if (njs_is_power_of_two(size)) {
discrete = njs_is_power_of_two(size);

#if (NJS_HAVE_ADDRESS_SANITIZER)
/* Keep the sanitizer redzone right after the object. */
discrete = 1;
#endif

if (discrete) {
block = njs_malloc(sizeof(njs_mp_block_t));
if (njs_slow_path(block == NULL)) {
return NULL;
Expand Down
47 changes: 29 additions & 18 deletions src/njs_regexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1263,9 +1263,9 @@ 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, length;
const u_char *p, *next;
njs_str_t rep, m;
int64_t n, last_index, ncaptures, pos, length, next, mlength;
const u_char *p, *start;
njs_str_t rep, m, head, tail;
njs_int_t ret;
njs_arr_t results;
njs_chb_t chain;
Expand All @@ -1275,7 +1275,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
njs_value_t *arguments, *r, *rx, *string, *replace;
njs_value_t s_lvalue, r_lvalue, value, matched, groups;
njs_function_t *func_replace;
njs_string_prop_t s;
njs_string_prop_t s, ms;

rx = njs_argument(args, 0);

Expand Down Expand Up @@ -1390,8 +1390,7 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
}

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

while (i < results.items) {
r = njs_arr_item(&results, i++);
Expand Down Expand Up @@ -1422,6 +1421,10 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,

pos = njs_max(njs_min(pos, (int64_t) length), 0);

mlength = njs_string_prop(vm, &ms, &matched);

p = njs_string_offset(&s, pos);

ret = njs_object_length(vm, r, &ncaptures);
if (njs_slow_path(ret != NJS_OK)) {
goto exception;
Expand Down Expand Up @@ -1466,9 +1469,19 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
}
}

ret = njs_string_get_substitution(vm, &matched, string, pos,
arguments, ncaptures, &groups,
replace, retval);
m.start = ms.start;
m.length = ms.size;

head.start = s.start;
head.length = p - s.start;

start = njs_string_offset(&s, njs_min(pos + mlength, length));
tail.start = (u_char *) start;
tail.length = (s.start + s.size) - start;

ret = njs_string_get_substitution(vm, &m, &head, &tail, arguments,
ncaptures, &groups, replace,
retval);

} else {
ret = njs_array_expand(vm, array, 0,
Expand Down Expand Up @@ -1501,17 +1514,14 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
goto exception;
}

p = njs_string_offset(&s, pos);

if (p >= next) {
njs_chb_append(&chain, next, p - next);
if (pos >= next) {
start = njs_string_offset(&s, next);
njs_chb_append(&chain, start, p - start);

njs_string_get(vm, retval, &rep);
njs_chb_append_str(&chain, &rep);

njs_string_get(vm, &matched, &m);

next = p + m.length;
next = pos + mlength;
}

if (!func_replace && njs_object_slots(r)) {
Expand All @@ -1524,8 +1534,9 @@ njs_regexp_prototype_symbol_replace(njs_vm_t *vm, njs_value_t *args,
}
}

if (next < s.start + s.size) {
njs_chb_append(&chain, next, s.start + s.size - next);
if (next < length) {
start = njs_string_offset(&s, next);
njs_chb_append(&chain, start, s.start + s.size - start);
}

ret = njs_string_create_chb(vm, retval, &chain);
Expand Down
61 changes: 33 additions & 28 deletions src/njs_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -2941,18 +2941,16 @@ njs_string_prototype_split(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,


njs_int_t
njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched,
njs_value_t *string, int64_t pos, njs_value_t *captures, int64_t ncaptures,
njs_string_get_substitution(njs_vm_t *vm, njs_str_t *matched, njs_str_t *head,
njs_str_t *tail, njs_value_t *captures, int64_t ncaptures,
njs_value_t *groups, njs_value_t *replacement, njs_value_t *retval)
{
u_char c, c2, *p, *r, *end;
size_t length;
int64_t tail, n;
njs_str_t rep, str, cap;
njs_int_t ret;
njs_chb_t chain;
njs_value_t name, value;
njs_string_prop_t s, m;
u_char c, c2, *p, *r, *end;
int64_t n;
njs_str_t rep, str, cap;
njs_int_t ret;
njs_chb_t chain;
njs_value_t name, value;

njs_string_get(vm, replacement, &rep);
p = rep.start;
Expand Down Expand Up @@ -2984,26 +2982,17 @@ njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched,
break;

case '&':
(void) njs_string_prop(vm, &m, matched);
njs_chb_append(&chain, m.start, m.size);
njs_chb_append_str(&chain, matched);
p += 2;
break;

case '`':
(void) njs_string_prop(vm, &s, string);
n = njs_string_offset(&s, pos) - s.start;
njs_chb_append(&chain, s.start, n);
njs_chb_append_str(&chain, head);
p += 2;
break;

case '\'':
length = njs_string_prop(vm, &m, matched);
(void) njs_string_prop(vm, &s, string);

tail = njs_string_offset(&s, pos + length) - s.start;

njs_chb_append(&chain, &s.start[tail],
njs_max((int64_t) s.size - tail, 0));
njs_chb_append_str(&chain, tail);
p += 2;
break;

Expand Down Expand Up @@ -3104,7 +3093,7 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
size_t length, size, end_of_last_match;
int64_t pos;
njs_int_t ret;
njs_str_t str;
njs_str_t str, m, head, tail;
njs_chb_t chain;
njs_value_t *this, *search, *replace;
njs_value_t search_lvalue, replace_lvalue, replacer, value,
Expand Down Expand Up @@ -3198,9 +3187,20 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
return NJS_OK;
}

m.start = s.start;
m.length = s.size;

if (!replaceAll) {
end = njs_string_offset(&string, pos);

if (func_replace == NULL) {
ret = njs_string_get_substitution(vm, search, this, pos, NULL, 0,
head.start = string.start;
head.length = end - string.start;

tail.start = (u_char *) end + s.size;
tail.length = (string.start + string.size) - (end + s.size);

ret = njs_string_get_substitution(vm, &m, &head, &tail, NULL, 0,
NULL, replace, &value);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
Expand All @@ -3223,8 +3223,6 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
}
}

end = njs_string_offset(&string, pos);

(void) njs_string_prop(vm, &ret_string, &value);

size = string.size + ret_string.size - s.size;
Expand All @@ -3247,8 +3245,16 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
start = string.start;

do {
end = njs_string_offset(&string, pos);

if (func_replace == NULL) {
ret = njs_string_get_substitution(vm, search, this, pos, NULL, 0,
head.start = string.start;
head.length = end - string.start;

tail.start = (u_char *) end + s.size;
tail.length = (string.start + string.size) - (end + s.size);

ret = njs_string_get_substitution(vm, &m, &head, &tail, NULL, 0,
NULL, replace, &value);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
Expand All @@ -3271,7 +3277,6 @@ njs_string_prototype_replace(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
}
}

end = njs_string_offset(&string, pos);
(void) njs_string_prop(vm, &ret_string, &value);

njs_chb_append(&chain, start, end - start);
Expand Down
4 changes: 2 additions & 2 deletions src/njs_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ njs_int_t njs_string_atob(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,

njs_int_t njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
njs_int_t njs_string_get_substitution(njs_vm_t *vm, njs_value_t *matched,
njs_value_t *string, int64_t pos, njs_value_t *captures, int64_t ncaptures,
njs_int_t njs_string_get_substitution(njs_vm_t *vm, njs_str_t *matched,
njs_str_t *head, njs_str_t *tail, njs_value_t *captures, int64_t ncaptures,
njs_value_t *groups, njs_value_t *replacement, njs_value_t *retval);


Expand Down
51 changes: 51 additions & 0 deletions src/test/njs_unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -10138,6 +10138,57 @@ static njs_unit_test_t njs_test[] =
"'abc'.replaceAll(re, '@$1|$2|$3|$4|$99|$100|@')"),
njs_str("@|X||Y|Z|0|@") },

{ njs_str("var n = 0, s = 'αβγ';"
"var re = {global: false, flags: '', exec: () =>"
" n++ ? null : {0: 'y'.repeat(100), index: 0}};"
"RegExp.prototype[Symbol.replace].call(re, s, \"[$']\")"),
njs_str("[]") },

{ njs_str("var n = 0, s = 'αβγδε';"
"var re = {global: false, flags: '', exec: () =>"
" n++ ? null : {0: 'y'.repeat(1000), index: 2}};"
"RegExp.prototype[Symbol.replace].call(re, s, \"<$'>\")"),
njs_str("αβ<>") },

{ njs_str("var n = 0, s = 'αβγ';"
"var re = {global: false, flags: '', exec: () =>"
" n++ ? null : {0: 'y', index: 0}};"
"RegExp.prototype[Symbol.replace].call(re, s, '')"),
njs_str("βγ") },

{ njs_str("var n = 0, s = 'αβγ';"
"var re = {global: false, flags: '', exec: () =>"
" n++ ? null : {0: 'y', index: 1e9}};"
"RegExp.prototype[Symbol.replace].call(re, s, '[$`]')"),
njs_str("αβγ[αβγ]") },

{ njs_str("var n = 0, s = 'αβγδ';"
"var re = {global: false, flags: '', exec: () =>"
" n++ ? null : {0: 'αβ', index: 1}};"
"RegExp.prototype[Symbol.replace].call(re, s, \"[$&|$`|$']\")"),
njs_str("α[αβ|α|δ]δ") },

{ njs_str("var n = 0, s = 'αβγδεζ';"
"var a = [{0: 'y', index: 5}, {0: 'y', index: 0}];"
"var re = {global: true, flags: 'g',"
" exec: () => n < a.length ? a[n++] : null};"
"RegExp.prototype[Symbol.replace].call(re, s, '<$&>')"),
njs_str("αβγδε<y>") },

{ njs_str("var n = 0;"
"var a = [{0: 'yyyy', index: 0}, {0: 'z', index: 3}];"
"var re = {global: true, flags: 'g',"
" exec: () => n < a.length ? a[n++] : null};"
"RegExp.prototype[Symbol.replace].call(re, 'abc', '[1]')"),
njs_str("[1]") },

{ njs_str("var n = 0;"
"var re = {global: false, flags: '', exec: () =>"
" n++ ? null : {0: 'yyyyyyyyy', index: 1}};"
"RegExp.prototype[Symbol.replace].call(re, 'abcdef',"
" \"[$&|$`|$']\")"),
njs_str("a[yyyyyyyyy|a|]") },

{ njs_str("var a = [];"
"Object.defineProperty(a, 32768, {});"
"var re = /any_regexp/;"
Expand Down
Loading