Skip to content

<regex>: Revise complexity limit - #6005

Merged
Stephan T. Lavavej (StephanTLavavej) merged 5 commits into
microsoft:mainfrom
muellerj2:regex-revise-complexity-limit
Jan 15, 2026
Merged

Stephan T. Lavavej (StephanTLavavej) merged 5 commits into
microsoft:mainfrom
muellerj2:regex-revise-complexity-limit

Conversation

@muellerj2

Copy link
Copy Markdown

Resolves #5944.

This limits the number of state transitions by a complexity limit that grows linearly in the length of the input string. Additionally, this also takes into account the length of string comparisons in _N_str and _N_back nodes (though divided by 64, as comparing one character is much cheaper than a single state transition).

I implemented a complexity limit of 300000 + 256 * input string length. I think that should be enough for reasonable uses (and it's likely this limit will become more generous in practice when #5971 is addressed): Matching the regex a* currently performs about 3 state transitions per matched character, so 85 such loops can be tried before a complexity exception is thrown.

The limit might be larger than what can fit into _Iter_diff_t<_It> (or ptrdiff_t). For this reason, two counter variables are used to implement the limit.

Drive-by change: I somehow missed that _Matcher3::_Pop_frame() is no longer in use, so this PR removes this function as well.

@muellerj2
Julian Müller (muellerj2) requested a review from a team as a code owner January 10, 2026 16:21
@github-project-automation github-project-automation Bot moved this to Initial Review in STL Code Reviews Jan 10, 2026
@muellerj2 Julian Müller (muellerj2) changed the title s<regex>: Revise complexity limit <regex>: Revise complexity limit Jan 10, 2026
@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) added enhancement Something can be improved regex meow is a substring of homeowner labels Jan 10, 2026
@StephanTLavavej

This comment was marked as resolved.

@muellerj2

Copy link
Copy Markdown
Author

I guess we could also use long long and clamp the limit at LLONG_MAX. A computation should still run for decades until it reaches LLONG_MAX.

The current solution just avoids this clamping.

@muellerj2

Copy link
Copy Markdown
Author

I pushed an alternative implementation of the complexity limit using a long long counter, which is simpler but not completely future-proof. Feel free to choose the solution you prefer.

Comment thread stl/inc/regex Outdated
Comment thread stl/inc/regex
Comment thread tests/std/tests/VSO_0000000_regex_use/test.cpp Outdated
@StephanTLavavej

Copy link
Copy Markdown
Member

Thanks! 😻 The single long long is much easier to reason about.

@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) moved this from Initial Review to Ready To Merge in STL Code Reviews Jan 13, 2026
@StephanTLavavej

Copy link
Copy Markdown
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) moved this from Ready To Merge to Merging in STL Code Reviews Jan 15, 2026
@StephanTLavavej
Stephan T. Lavavej (StephanTLavavej) merged commit e98005d into microsoft:main Jan 15, 2026
45 checks passed
@github-project-automation github-project-automation Bot moved this from Merging to Done in STL Code Reviews Jan 15, 2026
@StephanTLavavej

Copy link
Copy Markdown
Member

🕵️ 📈 🛑

Alexandros Konstantonis (alexandrosk0) added a commit to alexandrosk0/Smatchet that referenced this pull request Oct 6, 2026
…skip formats a line cannot match (#2312)

Built with MSVC 14.51 or newer, whose STL allows one regex_search call
300000 + 256 * length state transitions in total (microsoft/STL#6005),
ParseCallstackText let std::regex_error escape on lines its three format
regexes scan without matching. The windows-11-arm runner image moved to
that toolset on 2026-09-30, which turned the Windows-on-ARM lane red on
every develop run since. The parser's one product caller runs on the UI
thread with no try/catch.

- Every regex_search in TryParsePathLinePair goes through
  RegexSearchNoThrow. A search the matcher refuses counts as "this
  format did not match": the remaining formats still run and nothing
  leaves the parser. The parser stays Logger-free because the fuzz
  target links it without a logger.
- A format's regex runs only when the line holds the pair its
  line-number capture needs: '(' then a digit for the MSVC format,
  ':' then a digit for the other two. The patterns now capture [0-9]+,
  so that test and the regexes agree in any locale.

Results are unchanged for every line the old parser handled: old and new
parsers give byte-identical output over 400,000 generated lines on the
old-limit STL.

Known limit, tracked in #2311: under the 14.51 limit a real MSVC-format
frame behind an unbroken token of about 384+ characters on the same line
is dropped, because the first format gives up before reaching it.

Also adds an infra backlog entry on why a runner-image change sat red on
a push-only lane for 12 develop runs.

Fixes #2303

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Something can be improved regex meow is a substring of homeowner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

<regex>: Revising the stack and complexity limits

3 participants