From c8a3ecc3bcb36f0259f4d8ad2e0cdfcdc3183c9f Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 12:39:43 -0300 Subject: A regular expression search is bounded by a step budget patched into mvzr, not windows and a repeat cap The windows returned wrong matches: a candidate reaching a window's edge was left to the next window, half a window on, which could answer a match starting mid-token rather than the leftmost, and addr then pointed data's next write at the wrong bytes. The repeat cap missed mvzr's own worst case, a chain of a?, and alternation under a repeat, each exponential inside one mvzr call the deadline could not interrupt; and it refused ordinary s/S patterns. build.zig now patches the fetched mvzr at build time with a step counter on its backtracking recursion (matchPattern), so a fresh fetch keeps it and a moved anchor stops the build; regexp.zig gives each compiled pattern a budget, about 300 ms here, and a search that spends it fails as taking too long. Windows, the cap and their special cases are gone, and matches are exact again. Co-Authored-By: Claude Opus 5.5 --- src/normal.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/normal.zig') diff --git a/src/normal.zig b/src/normal.zig index 09e06b13..da707e26 100644 --- a/src/normal.zig +++ b/src/normal.zig @@ -92,7 +92,8 @@ pub fn applySelRegex(p: *Pardes, pane: *Pane, t: *Text, pat: []const u8, split: const snap = pane.sel_snap[0..pane.nsel_snap]; var out: [Text.max_selections]modal.Selection = undefined; var m: usize = 0; - if (regexp.Regex.compile(pat)) |re| { + if (regexp.Regex.compile(pat)) |compiled| { + var re = compiled; var hay_all = text; if (for (pat) |c| { if (std.ascii.isUpper(c)) break false; -- cgit v1.3