From 6675372c93201e4d456b88892a1d6045a70a9cad Mon Sep 17 00:00:00 2001 From: Carter Snook Date: Tue, 25 Aug 2026 11:09:39 -0500 Subject: [PATCH] support regexp buffer boundaries --- libregexp-opcode.h | 1 + libregexp.c | 50 +++++++++++++++++++++++++++++++++++++++------- test262.conf | 1 + 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/libregexp-opcode.h b/libregexp-opcode.h index b3d7b6fdf..27f7e2612 100644 --- a/libregexp-opcode.h +++ b/libregexp-opcode.h @@ -37,6 +37,7 @@ DEF(line_start, 1) DEF(line_start_m, 1) DEF(line_end, 1) DEF(line_end_m, 1) +DEF(line_end_z, 1) /* optional line terminator or "\r\n" followed by buffer end */ DEF(goto, 5) DEF(split_goto_first, 5) DEF(split_next_first, 5) diff --git a/libregexp.c b/libregexp.c index c387f0043..c0b17d168 100644 --- a/libregexp.c +++ b/libregexp.c @@ -2089,6 +2089,27 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) p = p1; } break; + case 'A': + if (s->is_unicode) { + p += 2; + re_emit_op(s, REOP_line_start); + break; + } + goto parse_class_atom; + case 'z': + if (s->is_unicode) { + p += 2; + re_emit_op(s, REOP_line_end); + break; + } + goto parse_class_atom; + case 'Z': + if (s->is_unicode) { + p += 2; + re_emit_op(s, REOP_line_end_z); + break; + } + goto parse_class_atom; case '0': p += 2; c = 0; @@ -2994,13 +3015,28 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, break; case REOP_line_end: case REOP_line_end_m: - if (cptr == cbuf_end) - break; - if (opcode == REOP_line_end) - goto no_match; - PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); - if (!is_line_terminator(c)) - goto no_match; + case REOP_line_end_z: + { + const uint8_t *cptr1 = cptr; + if (cptr1 == cbuf_end) + break; + if (opcode == REOP_line_end) + goto no_match; + GET_CHAR(c, cptr1, cbuf_end, cbuf_type); + if (!is_line_terminator(c)) + goto no_match; + if (opcode == REOP_line_end_z && cptr1 != cbuf_end) { + if (c == '\r') { + /* allow "\r\n" at end of buffer */ + GET_CHAR(c, cptr1, cbuf_end, cbuf_type); + if (c != '\n' || cptr1 != cbuf_end) { + goto no_match; + } + } else { + goto no_match; + } + } + } break; case REOP_dot: if (cptr == cbuf_end) diff --git a/test262.conf b/test262.conf index af5cd6474..f3a23c48a 100644 --- a/test262.conf +++ b/test262.conf @@ -179,6 +179,7 @@ Reflect Reflect.construct Reflect.set Reflect.setPrototypeOf +regexp-buffer-boundaries regexp-dotall regexp-duplicate-named-groups regexp-lookbehind