Skip to content

v2026.7.16

Choose a tag to compare

@github-actions github-actions released this 05 Jul 03:13

A strict drop-in policy — reject, don't silently fall back to backtracking.

The std::regex and re drop-ins used to differ: the Python binding rejected an unsupported pattern, while
real::compat silently fell back to std::regex — reintroducing the ReDoS the library exists to avoid, on
exactly the patterns a caller can least audit. Both are now strict by default.

  • A pattern the linear engine cannot represent (a backreference, a conditional, an unbounded lookaround) is
    rejected, not silently delegated — so every accepted pattern is a linear-time, ReDoS-safe guarantee.
    In C++ that is a regex_error with error_complexity and a REAL-identifiable message; in Python, a
    real.error. A pattern invalid for both engines still reports the standard library's own error code,
    so a syntax error stays a syntax error — a true drop-in there.
  • Fallback is opt-in and observable. real::compat::regex(pat, flags, policy::fallback) in C++, and
    real.compile(pat, fallback=True) (or module-wide real.fallback = True) in Python, restore delegation
    to std::regex / re for ineligible patterns — forfeiting the linear-time guarantee for those. uses_real()
    / uses_fallback() / policy() (C++) and Pattern.engine (Python, "real" or "re") always tell you
    which backend backs a pattern.

Also: the dev tooling is consolidated under tools/ (the Unicode-table codegen joins the layering check).
This changes the compat default while it is still pre-adoption; migrate a caller that wants the old behaviour
by passing policy::fallback / fallback=True. See COMPATIBILITY.md's "The drop-in policy".