/** * ReDoS guard for `pattern` validators (CLAUDE.md engine invariant: patterns * nesting unbounded quantifiers are rejected). A small tokenizer turns the * source into groups/alternatives/quantified items, then flags any group * repeated more than twice whose body can be split between iterations in * more than one way — the shape that makes a backtracking engine go * exponential (or high-degree polynomial for a large bounded repeat): * * - every mandatory item of an alternative is itself unbounded: * `(a+)+`, `((a+))+`, `(?a+)+`, `(\w+\s?)+`, `(x+x+)+`, `(a*)*` * - one alternative is unbounded on its own: `(a+|b)+` * - two alternatives are spelled the same: `(a|a)+` * - two alternatives can start on the same character, or one can match * nothing: `(\w|\d)+`, `(a|ab)+`, `(a|a?)+` * - an unbounded item can swallow the character that ends its iteration: * `(.*a){12}`, `(a+b?)+` * - three or more adjacent unbounded runs share a character: `\d*\d*\d*x` * (cubic and worse; two runs stay quadratic and are left to the length cap) * * Character overlap is decided by testing each atom against a fixed sample of * characters (ASCII plus a few non-ASCII classes), so it can miss an overlap * that lives only outside the sample. A mandatory bounded atom that the * unbounded part cannot consume (`(-[a-z]+)*`, `(abc+)+`) anchors each * iteration and is accepted. Patterns are builder-authored: the guard * catches authoring mistakes at save time, and the validator also caps the * input length a pattern runs on. A linear-time engine is the real fix. */ /** * True when `source` backtracks catastrophically on hostile input (see module * doc). Sources that do not compile return false — callers report those as * invalid separately. */ export declare function isUnsafePattern(source: string): boolean;