[njs] Fixed String.prototype.replace() with replacement containing "$'", "$`".
Dmitry Volyntsev
xeioex at nginx.com
Wed Mar 8 05:09:25 UTC 2023
details: https://hg.nginx.org/njs/rev/10127d70e941
branches:
changeset: 2068:10127d70e941
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Mar 07 20:51:45 2023 -0800
description:
Fixed String.prototype.replace() with replacement containing "$'", "$`".
Previously, the resulting string was might be broken when the string to
replace and the search string were UTF-8. pos is always a character
offset, it should not be directly used as a byte size or offset.
diffstat:
src/njs_string.c | 36 ++++++++++++++++++++----------------
src/test/njs_unit_test.c | 11 +++++++++++
2 files changed, 31 insertions(+), 16 deletions(-)
diffs (82 lines):
diff -r 107c7098bd6d -r 10127d70e941 src/njs_string.c
--- a/src/njs_string.c Tue Mar 07 20:38:08 2023 -0800
+++ b/src/njs_string.c Tue Mar 07 20:51:45 2023 -0800
@@ -3476,12 +3476,14 @@ njs_string_get_substitution(njs_vm_t *vm
njs_value_t *string, int64_t pos, njs_value_t *captures, int64_t ncaptures,
njs_value_t *groups, njs_value_t *replacement, njs_value_t *retval)
{
- int64_t tail, n;
- u_char c, c2, *p, *r, *end;
- njs_str_t rep, m, str, cap;
- njs_int_t ret;
- njs_chb_t chain;
- njs_value_t name, value;
+ 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;
njs_string_get(replacement, &rep);
p = rep.start;
@@ -3513,24 +3515,26 @@ njs_string_get_substitution(njs_vm_t *vm
break;
case '&':
- njs_string_get(matched, &m);
- njs_chb_append_str(&chain, &m);
+ (void) njs_string_prop(&m, matched);
+ njs_chb_append(&chain, m.start, m.size);
p += 2;
break;
case '`':
- njs_string_get(string, &str);
- njs_chb_append(&chain, str.start, pos);
+ (void) njs_string_prop(&s, string);
+ n = njs_string_offset(&s, pos) - s.start;
+ njs_chb_append(&chain, s.start, n);
p += 2;
break;
case '\'':
- njs_string_get(matched, &m);
- tail = pos + m.length;
-
- njs_string_get(string, &str);
- njs_chb_append(&chain, &str.start[tail],
- njs_max((int64_t) str.length - tail, 0));
+ length = njs_string_prop(&m, matched);
+ (void) njs_string_prop(&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));
p += 2;
break;
diff -r 107c7098bd6d -r 10127d70e941 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Tue Mar 07 20:38:08 2023 -0800
+++ b/src/test/njs_unit_test.c Tue Mar 07 20:51:45 2023 -0800
@@ -8887,6 +8887,17 @@ static njs_unit_test_t njs_test[] =
{ njs_str("'abcdbe'.replaceAll('b', '|$`X$\\'|')"),
njs_str("a|aXcdbe|cd|abcdXe|e") },
+ { njs_str("var r = 'αβγ'.replace('β', \"$'\"); [r, r.length]"),
+ njs_str("αγγ,3") },
+
+ { njs_str("var r = 'αβγαβγ'.replaceAll('β', \"$'\"); [r, r.length]"),
+ njs_str("αγαβγγαγγ,9") },
+
+ { njs_str("var r = 'αβγ'.replace('β', \"$`\"); [r, r.length]"),
+ njs_str("ααγ,3") },
+
+ { njs_str("var r = 'αβγαβγ'.replaceAll('β', \"$`\"); [r, r.length]"),
+ njs_str("ααγααβγαγ,9") },
{ njs_str("'ABC'.replace('B', '$<g>')"),
njs_str("A$<g>C") },
More information about the nginx-devel
mailing list