Skip to content

[release/10.0] Fix incorrect atomic loop optimization when body contains backtracking#124287

Merged
jeffhandley merged 1 commit intorelease/10.0from
backport/pr-124254-to-release/10.0
Feb 16, 2026
Merged

[release/10.0] Fix incorrect atomic loop optimization when body contains backtracking#124287
jeffhandley merged 1 commit intorelease/10.0from
backport/pr-124254-to-release/10.0

Conversation

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented Feb 11, 2026

Backport of #124254 to release/10.0

/cc @stephentoub

Customer Impact

  • Customer reported
  • Found internally

Regexes with various backtracking constructs nested inside loops can produce the wrong results. The only workaround is to change the pattern.

Regression

  • Yes
  • No

.NET 10, P6 or P7

Testing

Added a bunch of new patterns to the test suite.

Risk

Low. It's disabling an optimization in additional cases. The main risk would be if it removed the optimization in cases where it's still ok, but such an optimization was only added in .NET 10.

MakeLoopAtomic wraps a loop in an Atomic group, which discards all backtracking state from the body. However, CanBeMadeAtomic only proves that giving back iterations is unnecessary... it does not account for within-body backtracking. When the body itself contains backtracking constructs, the atomic wrapper incorrectly suppresses that internal backtracking, producing wrong match results.

The fix adds a MayContainBacktracking check that walks the loop body tree before allowing MakeLoopAtomic. A loop is only made atomic when the body has no backtracking constructs of its own. The backtracking-construct detection logic is extracted into a reusable IsBacktrackingConstruct property on RegexNode, which RegexTreeAnalyzer now also uses, removing the duplicated switch.

Tests are added covering lazy/greedy single-char loops, char-class loops, alternations, and general multi-char loops inside outer loop bodies, as well as cases where the optimization should still apply (non-backtracking bodies).
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-text-regularexpressions
See info in area-owners.md if you want to be subscribed.

Copy link
Member

@artl93 artl93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

customer reported. regression in 10. approved.

Copy link
Member

@artl93 artl93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Customer reported. Regression. Approved.

@jeffhandley
Copy link
Member

/ba-g Unrelated failure in a FileSystemWatcher test on 1 platform

@jeffhandley jeffhandley merged commit dd25d91 into release/10.0 Feb 16, 2026
91 of 98 checks passed
@jeffhandley jeffhandley deleted the backport/pr-124254-to-release/10.0 branch February 16, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments