From: Dmitry Volyntsev Date: Tue, 4 Jun 2019 09:45:06 +0000 (+0300) Subject: Handling zero byte characters inside RegExp pattern strings. X-Git-Tag: 0.3.3~18 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=d14fed64975e3168346038a5ce5e11534ad84b57;p=njs.git Handling zero byte characters inside RegExp pattern strings. Fixed heap-buffer-overflow in RegExp.prototype.source. This closes #168 issue on Github. --- diff --git a/njs/njs_regexp.c b/njs/njs_regexp.c index 03a3003a..a78025f4 100644 --- a/njs/njs_regexp.c +++ b/njs/njs_regexp.c @@ -207,17 +207,19 @@ njs_regexp_create(njs_vm_t *vm, njs_value_t *value, u_char *start, /* - * PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with + * 1) PCRE with PCRE_JAVASCRIPT_COMPAT flag rejects regexps with * lone closing square brackets as invalid. Whereas according * to ES6: 11.8.5 it is a valid regexp expression. * + * 2) escaping zero byte characters as "\u0000". + * * Escaping it here as a workaround. */ nxt_inline njs_ret_t njs_regexp_escape(njs_vm_t *vm, nxt_str_t *text) { - size_t brackets; + size_t brackets, zeros; u_char *p, *dst, *start, *end; nxt_bool_t in; @@ -225,6 +227,7 @@ njs_regexp_escape(njs_vm_t *vm, nxt_str_t *text) end = text->start + text->length; in = 0; + zeros = 0; brackets = 0; for (p = start; p < end; p++) { @@ -244,14 +247,24 @@ njs_regexp_escape(njs_vm_t *vm, nxt_str_t *text) case '\\': p++; + + if (p == end || *p != '\0') { + break; + } + + /* Fall through. */ + + case '\0': + zeros++; + break; } } - if (!brackets) { + if (!brackets && !zeros) { return NXT_OK; } - text->length = text->length + brackets; + text->length = text->length + brackets + zeros * nxt_length("\\u0000"); text->start = nxt_mp_alloc(vm->mem_pool, text->length); if (nxt_slow_path(text->start == NULL)) { @@ -283,6 +296,16 @@ njs_regexp_escape(njs_vm_t *vm, nxt_str_t *text) if (p == end) { goto done; } + + if (*p != '\0') { + break; + } + + /* Fall through. */ + + case '\0': + dst = nxt_cpymem(dst, "\\u0000", 6); + continue; } *dst++ = *p; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 204281cb..e400ad52 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -5564,6 +5564,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("/]cd/"), nxt_string("/\\]cd/") }, + { nxt_string("RegExp('\\\\0').source[1]"), + nxt_string("0") }, + { nxt_string("']'.match(/]/)"), nxt_string("]") }, @@ -12812,6 +12815,27 @@ static njs_unit_test_t njs_regexp_test[] = { nxt_string("/[\\uFDE0-\\uFFFD]/g; export default 1"), nxt_string("SyntaxError: Illegal export statement in 1") }, + + { nxt_string("RegExp(RegExp('\x00]]')).test('\x00]]')"), + nxt_string("true") }, + + { nxt_string("RegExp('\0').test('\0')"), + nxt_string("true") }, + + { nxt_string("RegExp('\x00').test('\0')"), + nxt_string("true") }, + + { nxt_string("RegExp('\x00\\\\x00').source"), + nxt_string("\\u0000\\x00") }, + + { nxt_string("/\\\0/"), + nxt_string("/\\\\u0000/") }, + + { nxt_string("RegExp('\\\\\\0').source"), + nxt_string("\\\\u0000") }, + + { nxt_string("RegExp('[\0]').test('\0')"), + nxt_string("true") }, };