mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-19 05:50:27 +00:00
terminal: bound link regex search work with Oniguruma retry limits (#11181)
Fixes #11177 Use per-search Oniguruma match params (retry_limit_in_search) in StringMap-backed link detection to avoid pathological backtracking hangs on very long lines. The units are ticks in the internal loop so its kind of opaque but this seems to still match some very long URLs. The test case in question was a 169K character line (which is now rejected).
This commit is contained in:
@@ -11,6 +11,12 @@ const Screen = @import("Screen.zig");
|
||||
const Pin = @import("PageList.zig").Pin;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// Retry budget for StringMap regex searches.
|
||||
//
|
||||
// Units are Oniguruma retry steps (internal backtracking/retry counter),
|
||||
// not bytes/characters/time.
|
||||
const oni_search_retry_limit = 100_000;
|
||||
|
||||
string: [:0]const u8,
|
||||
map: []Pin,
|
||||
|
||||
@@ -44,11 +50,26 @@ pub const SearchIterator = struct {
|
||||
pub fn next(self: *SearchIterator) !?Match {
|
||||
if (self.offset >= self.map.string.len) return null;
|
||||
|
||||
var region = self.regex.search(
|
||||
// Use per-search match params so we can bound regex retry steps
|
||||
// (Oniguruma's internal backtracking work counter).
|
||||
var match_param = try oni.MatchParam.init();
|
||||
defer match_param.deinit();
|
||||
try match_param.setRetryLimitInSearch(oni_search_retry_limit);
|
||||
|
||||
var region = self.regex.searchWithParam(
|
||||
self.map.string[self.offset..],
|
||||
.{},
|
||||
&match_param,
|
||||
) catch |err| switch (err) {
|
||||
error.Mismatch => {
|
||||
// Retry/stack-limit errors mean we hit our work budget and
|
||||
// aborted matching.
|
||||
// For iterator callers this is equivalent to "no further matches".
|
||||
error.Mismatch,
|
||||
error.RetryLimitInMatchOver,
|
||||
error.RetryLimitInSearchOver,
|
||||
error.MatchStackLimitOver,
|
||||
error.SubexpCallLimitInSearchOver,
|
||||
=> {
|
||||
self.offset = self.map.string.len;
|
||||
return null;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user