Skip to main content

Text Patterns

This page explains how a rule can check text against a pattern safely, without exposing it to catastrophic backtracking.

The regular-expression subset

matches and regexMatch share one enumerated, portable JS subset — restricted to constructs that behave identically across V8, SpiderMonkey and JavaScriptCore, because the isomorphism claim (ENG-16) must be honest rather than "identical on the engines we happened to test", and the browser editor must never validate a pattern the Node runtime would match differently.

  • Permitted flags: i, m, s — generated as PERMITTED_REGEX_FLAGS on the Operators & Precedence page. g and y are excluded because they make a compiled pattern stateful through its own last-index, which is not a pure predicate. u and v are excluded because they change character-class and escape semantics and reach Unicode property escapes. d is excluded because it adds match indices no operator consumes.
  • Excluded constructs: lookahead (positive and negative) and lookbehind are not part of the dialect — no catalog operator needs them, and nested or repeated lookaheads are exactly where first-character analysis stops being decidable. Named capture groups are excluded as well. The construct walker is conservative by construction: an unrecognised construct is always rejected, never admitted by omission.
  • The two rejected backtracking shapes, kept out of the dialect for ReDoS prevention: an unbounded quantifier applied to a group that itself contains an unbounded quantifier (nested unbounded repetition), and an unbounded-quantified group whose alternation branches have overlapping possible first characters. Both can backtrack exponentially on adversarial input, and both are rejected at save time — the only layer that gives an author a diagnostic instead of a mystery timeout.
  • The input cap: REGEX_INPUT_MAX_LENGTH (generated on the catalog page) bounds the length of the subject text a checked pattern is ever applied to, as a second, independent layer alongside the construct restrictions — Piscina's own wall-clock and memory limits remain the backstop behind both.
  • matches requires the pattern to match the subject's whole length; a pattern that already anchors itself with ^ or $ is refused, because the engine cannot safely add its own whole-subject anchoring around one. regexMatch matches anywhere in the subject and has no such restriction.

This is a save-time security control on untrusted, tenant-authored pattern text (T-02-02), not a convenience restriction — a wider dialect is additive later; narrowing it would invalidate saved rulesets.