Welcome! Log In Create A New Profile

Advanced

[njs] Fixed heap-buffer-overflow for RegExp.prototype[Symbol.replace].

Alexander Borisov
October 13, 2020 08:46AM
details: https://hg.nginx.org/njs/rev/a82f123409b7
branches:
changeset: 1539:a82f123409b7
user: Alexander Borisov <alexander.borisov@nginx.com>
date: Tue Oct 13 15:44:33 2020 +0300
description:
Fixed heap-buffer-overflow for RegExp.prototype[Symbol.replace].

Previously, RegExp.prototype[Symbol.replace] might overrun the boundaries
of the result of the custom "exec" method for a RegExp argument. The
issue occurred when the result object had zero length. The length is
used to create an array and the zero index was always written without
respect for the length resulting is heap-buffer-overflow.

The issue was introduced in 1c729f765cfb.

diffstat:

src/njs_regexp.c | 14 ++++++++------
src/test/njs_unit_test.c | 12 ++++++++++++
2 files changed, 20 insertions(+), 6 deletions(-)

diffs (72 lines):

diff -r 893fa730285c -r a82f123409b7 src/njs_regexp.c
--- a/src/njs_regexp.c Thu Oct 08 18:47:04 2020 +0300
+++ b/src/njs_regexp.c Tue Oct 13 15:44:33 2020 +0300
@@ -1343,14 +1343,14 @@ njs_regexp_prototype_symbol_replace(njs_

pos = njs_max(njs_min(pos, (int64_t) s.size), 0);

- if (njs_fast_path(njs_is_fast_array(r))) {
+ if (njs_fast_path(njs_is_fast_array(r) && njs_array_len(r) != 0)) {
array = njs_array(r);

arguments = array->start;
arguments[0] = matched;
- ncaptures = array->length;
+ ncaptures = njs_max((int64_t) array->length - 1, 0);

- for (n = 1; n < ncaptures; n++) {
+ for (n = 1; n <= ncaptures; n++) {
if (njs_is_undefined(&arguments[n])) {
continue;
}
@@ -1367,7 +1367,9 @@ njs_regexp_prototype_symbol_replace(njs_
goto exception;
}

- array = njs_array_alloc(vm, 0, ncaptures, 0);
+ ncaptures = njs_max(ncaptures - 1, 0);
+
+ array = njs_array_alloc(vm, 0, ncaptures + 1, 0);
if (njs_slow_path(array == NULL)) {
goto exception;
}
@@ -1375,7 +1377,7 @@ njs_regexp_prototype_symbol_replace(njs_
arguments = array->start;
arguments[0] = matched;

- for (n = 1; n < ncaptures; n++) {
+ for (n = 1; n <= ncaptures; n++) {
ret = njs_value_property_i64(vm, r, n, &arguments[n]);
if (njs_slow_path(ret == NJS_ERROR)) {
goto exception;
@@ -1406,7 +1408,7 @@ njs_regexp_prototype_symbol_replace(njs_
}

ret = njs_string_get_substitution(vm, &matched, string, pos,
- arguments, ncaptures - 1, &groups,
+ arguments, ncaptures, &groups,
replace, &retval);

} else {
diff -r 893fa730285c -r a82f123409b7 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Thu Oct 08 18:47:04 2020 +0300
+++ b/src/test/njs_unit_test.c Tue Oct 13 15:44:33 2020 +0300
@@ -8284,6 +8284,18 @@ static njs_unit_test_t njs_test[] =
{ njs_str("/b(c)(z)?(.)/[Symbol.replace]('abcde', '[$01$02$03$04$00]')"),
njs_str("a[cd$04$00]e") },

+ { njs_str("var r = /./; r.exec = () => {return {}};"
+ "r[Symbol.replace]('ABCD', 'b')"),
+ njs_str("b") },
+
+ { njs_str("var r = /./; r.exec = () => {return {}};"
+ "r[Symbol.replace]('ABCD', (m,p,o) => `${m}|${p}|${o}`)"),
+ njs_str("undefined|0|ABCD") },
+
+ { njs_str("var r = /./; r.exec = () => Buffer.from([]).toJSON().data;"
+ "r[Symbol.replace]('ABCD', 'b')"),
+ njs_str("b") },
+
{ njs_str("'α'.replace(/(h*)/g, '$1βγ')"),
njs_str("βγαβγ") },

_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[njs] Fixed heap-buffer-overflow for RegExp.prototype[Symbol.replace].

Alexander Borisov 374 October 13, 2020 08:46AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 167
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready