Skip to content

Comments

Fix: Allow inline regex options in conditional expression branches#124699

Open
danmoseley wants to merge 2 commits intodotnet:mainfrom
danmoseley:fix/111633-conditional-options
Open

Fix: Allow inline regex options in conditional expression branches#124699
danmoseley wants to merge 2 commits intodotnet:mainfrom
danmoseley:fix/111633-conditional-options

Conversation

@danmoseley
Copy link
Member

Fixes #111633.

Problem

The regex parser rejects inline options like (?i) inside the yes/no branches of expression conditionals (e.g. (?(test)(?i)yes|no)), throwing Unrecognized grouping construct. This is a regression from .NET Framework, introduced in corefx PR #16609.

BackreferenceConditional (e.g. (?(1)(?i)yes|no)) was never blocked, confirming the restriction on ExpressionConditional was unintentional.

Root Cause

In RegexParser.ScanGroupOpen(), ScanOptions() was skipped whenever _group.Kind == ExpressionConditional. This was intended to protect the test expression, but by the time we're parsing the yes/no branches, _group is still the ExpressionConditional node (the test expression is parsed inside its own sub-group). So the check blocked options in the branches rather than in the test.

Fix

Changed the condition to also check _group.ChildCount() > 0: options are only blocked when the conditional has no test expression yet (ChildCount == 0), allowing them in the branches after the test expression has been added (ChildCount > 0).

Testing

  • 5 new test cases for inline options in conditional branches (expression conditional, backreference conditional, lookahead conditional, options group syntax, options in no-branch)
  • All 30,801 existing regex tests pass on net11.0
  • All 1,980 tests pass on .NET Framework 4.8.1, confirming the patterns were always valid there
  • Verified the new tests fail without the code fix

@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
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a regression where inline regex options (e.g., (?i)) were incorrectly blocked inside the yes/no branches of expression conditionals like (?(test)(?i)yes|no). The root cause was an overly broad check that blocked options for the entire conditional instead of just the test expression. The fix distinguishes between parsing phases by checking if the test expression has been added (ChildCount() > 0), allowing options in branches but not in the test expression itself.

Changes:

  • Fixed RegexParser to allow inline options in conditional branches by checking ChildCount() > 0
  • Added tests for inline options in various conditional patterns
  • Added SetSearchValues optimization for interpreter character class matching with proper Multi literal encoding validation

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs Added ChildCount() > 0 check to allow inline options in conditional branches but not in test expressions
src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs Added 5 test cases for inline options in conditional branches; added regression test for Multi literal encoding validation
src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreterCode.cs Added SetSearchValues optimization with validation to prevent IndexOutOfRangeException on Multi literals resembling character class encodings
src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs Updated Setrep and Setloop opcodes to use SetSearchValues for vectorized matching in left-to-right mode

@danmoseley danmoseley force-pushed the fix/111633-conditional-options branch from e80a3d1 to 66a5e46 Compare February 21, 2026 04:44
Fixes dotnet#111633. The regex parser incorrectly rejected inline options
like (?i) inside the yes/no branches of expression conditionals
(e.g. (?(test)(?i)yes|no)), throwing InvalidGroupingConstruct.

The check in ScanGroupOpen blocked ScanOptions() whenever _group was
an ExpressionConditional, but this was too broad - it blocked options
in the branches, not just in the test expression. The fix narrows the
check to only block options when no test expression has been added yet
(ChildCount() == 0), allowing options in the branches (ChildCount > 0).

Note: BackreferenceConditional was never blocked, confirming this was
an unintentional inconsistency introduced in corefx PR dotnet#16609.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley danmoseley force-pushed the fix/111633-conditional-options branch from 66a5e46 to 7eb0fa8 Compare February 21, 2026 04:48
Copilot AI review requested due to automatic review settings February 21, 2026 04:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Verify that (?(?i)yes|no) is still rejected as InvalidGroupingConstruct,
ensuring the fix only allows options in yes/no branches, not as the test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@danmoseley
Copy link
Member Author

ready for review

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.

BUG or Feature? Conditional expressions cannot directly contain regex options in .NET 5 and later versions

1 participant