RegexOptions.Compiled Backtracking Regression on .NET 10 from .NET 8
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
A backtracking-prone pattern completes instantly on .NET 8 (both interpreted and compiled) hangs indefinitely on .NET 10 with `RegexOptions.Compiled`. I am able to reproduce on version 10.0.11.
### Reproduction Steps
`Program.cs` in a project targeting `net8.0;net10.0`:
```csharp
using System.Text.RegularExpressions;
// Optional numeric group, then
// Bounded lazy filler of tokens, then
// Numeric group, then
// Keyword alternation with a negative lookahead
const string pattern = @"\b(scan\w*|scanned|sc|print\w*|printed)\b\s+(?:(\d+(?:,\d{3})*[km]?)\s+)?(?:[A-Za-z0-9.-]+\s+){0,2}?(\d+(?:\.\d+)?)\s*(?:(a|b)\b|(reads?|writes?)\b(?!\s+cache))";
// Two non-matching lines
const string input = "scanned 12 foo 34 567 8.90 read 1.11\nprinted 12 foo 34 567 8.90 write 2.22";
var interpreted = new Regex(pattern, RegexOptions.IgnoreCase);
var compiled = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
Console.WriteLine($".NET {Environment.Version}");
Measure("interpreted", interpreted);
Measure("compiled", compiled);
void Measure(string name, Regex regex)
{
int count = 0;
var sw = System.Diagnostics.Stopwatch.StartNew();
var task = Task.Run(() =>
{
foreach (Match _ in regex.Matches(input))
{
count ++;
}
}
bool finished = task.Wait(TimeSpan.FromSeconds(10));
Console.WriteLine(finished
? $" {name,-11}: completed in {sw.ElapsedMilliseconds} ms ({count} matches)
: $" {name,-11}: DID NOT COMPLETE within 10s");
}
```
Run:
```
dotnet run -c Release -f net8.0
dotnet run -c Release -f net10.0
```
### Expected behavior
The compiled engine terminates quickly, matching the interpreted engine and .NET 8.
```
.NET 8.0.27
interpreted: completed in 1 ms (0 matches)
compiled : completed in 11 ms (0 matches)
```
### Actual behavior
On .NET 10 the compiled engine does not terminate, while the interpreted engine is fine.
```
.NET 10.0.11
interpreted: completed in 2 ms (0 matches)
compiled : DID NOT COMPLETE within 10s
```
### Regression?
Yes. Works on .NET 8.0.27 (both engines). Fails on .NET 10.0.8 and 10.0.11 (compiled only).
### Known Workarounds
Drop `RegexOptions.Compiled` (use the interpreted engine), or set a `matchTimeout` so the runaway throws `RegexMatchTimeoutException` instead of hanging.
### Configuration
* Reproduced on Microsoft.NETCore.App 10.0.8 and 10.0.11 (latest 10.0.x, 2026-08-11), Windows x64
* .NET SDK 10.0.300
* Not present on .NET 8.0.27 (baseline)
### Other information
_No response_
Contributor guide
Research direction
Run the supplied Program.cs reproduction in Release for net8.0 and net10.0, comparing interpreted and RegexOptions.Compiled execution. Trace the compiled regex path from the reported behavior and use the existing regex test area if locating it in the runtime is necessary. Done means the net10.0 compiled engine terminates quickly and reports zero matches, without requiring a timeout.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100