/*
- * 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;
end = text->start + text->length;
in = 0;
+ zeros = 0;
brackets = 0;
for (p = start; p < end; p++) {
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)) {
if (p == end) {
goto done;
}
+
+ if (*p != '\0') {
+ break;
+ }
+
+ /* Fall through. */
+
+ case '\0':
+ dst = nxt_cpymem(dst, "\\u0000", 6);
+ continue;
}
*dst++ = *p;
{ nxt_string("/]cd/"),
nxt_string("/\\]cd/") },
+ { nxt_string("RegExp('\\\\0').source[1]"),
+ nxt_string("0") },
+
{ nxt_string("']'.match(/]/)"),
nxt_string("]") },
{ 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") },
};