Follow-up to #3182 / PR #3317 (which fixed the Branch C lookahead ReDoS). This is the second, still-open csharp func_start backtracking trigger.
Impact / severity: priority: medium (not just speed)
Mechanism
A [...] run at a line start has three derivations:
- the attribute shield
^[ \t]*(?:\[[^\]]{0,250}\][ \t\n]*){0,5}
- single-char tokens in the return-type loop:
[a-zA-Z0-9_<>\[\]?.*] contains [ and ]
- the token alternative
\[[^\]]{0,80}\]
When no identifier + ( follows, the engine explores every combination before failing. That's exponential in adjacent brackets, repeated for each {0,5} shield count and up to {1,10} tokens. Worst observed: roslyn expected-output text [GetA][Get0][G1][operator]1True in code_stream costs 29s for one line-start attempt. Removing the attribute shield alone cuts an [InlineData] block ~6× (0.342s → 0.058s).
Repro: func_start.match(code_stream, <line start>) on line ~13791 of the file above, or stacked [InlineData(1, 2)] lines.
Fix options (why this isn't a drop-in like #3317)
- Atomic groups / possessive quantifiers (
(?>...), *+) would kill the ambiguity with minimal semantic change, but need Python ≥ 3.11. requires-python = ">=3.9" and CI still tests 3.9/3.10 on all three OSes. This is the cleanest route if we raise the floor to 3.11.
- On 3.9: emulate atomicity with
(?=(...))\1, or disambiguate (drop [/]/</> from the single-char class so brackets go only through their group alternatives). Both change accepted strings in edge cases, e.g. 3-level space-free generics A<B<C<D>>> or unbalanced x[. They need a parity policy: measure the function-set delta on the C# corpus (roslyn/runtime/PowerShell/crucible) and accept or reject it.
Acceptance
UserDefinedCompoundAssignmentOperatorsTests.cs under the fuse, with functions extracted.
- Match-set delta on the C# corpus reported (zero, or explicitly accepted).
- ReDoS regression tests for the
[InlineData] stack and the [GetA][Get0]... shape.
- Golden crucible both legs.
🤖 Generated with Claude Code
Follow-up to #3182 / PR #3317 (which fixed the Branch C lookahead ReDoS). This is the second, still-open csharp
func_startbacktracking trigger.Impact / severity: priority: medium (not just speed)
roslyn/src/Compilers/CSharp/Test/Emit3/Symbols/UserDefinedCompoundAssignmentOperatorsTests.cs(20k LOC) still exceeds the 60s worker fuse even with perf(#3182): linear csharp func_start Branch C lookahead (roslyn Optical −82%) #3317. Thefunc_startrule sweep overcode_streamalone takes ~250s. Because the fuse'sTimeoutErroris swallowed, the file ships with incomplete/zero structural data instead of being relegated.UnsignedRightShiftTests.cs41s. Stacked xunit[InlineData(...)]blocks cost ~16ms per line start across C# test suites (runtimeMathF.cs37s,Overlaps.cs17s, roslynNavigateToSearchIndexTests.cs12s). Residual roslyn after perf(#3182): linear csharp func_start Branch C lookahead (roslyn Optical −82%) #3317:csharp::Cartography_Mode_B_Braces75s +csharp::func_start44s (5,000-file sample).Mechanism
A
[...]run at a line start has three derivations:^[ \t]*(?:\[[^\]]{0,250}\][ \t\n]*){0,5}[a-zA-Z0-9_<>\[\]?.*]contains[and]\[[^\]]{0,80}\]When no identifier +
(follows, the engine explores every combination before failing. That's exponential in adjacent brackets, repeated for each{0,5}shield count and up to{1,10}tokens. Worst observed: roslyn expected-output text[GetA][Get0][G1][operator]1Trueincode_streamcosts 29s for one line-start attempt. Removing the attribute shield alone cuts an[InlineData]block ~6× (0.342s → 0.058s).Repro:
func_start.match(code_stream, <line start>)on line ~13791 of the file above, or stacked[InlineData(1, 2)]lines.Fix options (why this isn't a drop-in like #3317)
(?>...),*+) would kill the ambiguity with minimal semantic change, but need Python ≥ 3.11.requires-python = ">=3.9"and CI still tests 3.9/3.10 on all three OSes. This is the cleanest route if we raise the floor to 3.11.(?=(...))\1, or disambiguate (drop[/]/</>from the single-char class so brackets go only through their group alternatives). Both change accepted strings in edge cases, e.g. 3-level space-free genericsA<B<C<D>>>or unbalancedx[. They need a parity policy: measure the function-set delta on the C# corpus (roslyn/runtime/PowerShell/crucible) and accept or reject it.Acceptance
UserDefinedCompoundAssignmentOperatorsTests.csunder the fuse, with functions extracted.[InlineData]stack and the[GetA][Get0]...shape.🤖 Generated with Claude Code