}
}
- // Now run the DFA or NFA traversal from the current point using the current state.
+ // Now run the DFA or NFA traversal from the current point using the current state. If timeouts are being checked,
+ // we need to pop out of the inner loop every now and then to do the timeout check in this outer loop.
+ const int CharsPerTimeoutCheck = 10_000;
+ ReadOnlySpan<char> inputForInnerLoop = _checkTimeout && input.Length - i > CharsPerTimeoutCheck ?
+ input.Slice(0, i + CharsPerTimeoutCheck) :
+ input;
+
int finalStatePosition;
int findResult = currentState.NfaState is not null ?
- FindFinalStatePositionDeltas<NfaStateHandler>(builder, input, ref i, ref currentState, ref matchLength, out finalStatePosition) :
- FindFinalStatePositionDeltas<DfaStateHandler>(builder, input, ref i, ref currentState, ref matchLength, out finalStatePosition);
+ FindFinalStatePositionDeltas<NfaStateHandler>(builder, inputForInnerLoop, ref i, ref currentState, ref matchLength, out finalStatePosition) :
+ FindFinalStatePositionDeltas<DfaStateHandler>(builder, inputForInnerLoop, ref i, ref currentState, ref matchLength, out finalStatePosition);
// If we reached a final or deadend state, we're done.
if (findResult > 0)
// find result will be 0, otherwise negative.
if (findResult < 0)
{
- if ((uint)i >= (uint)input.Length)
+ if (i >= input.Length)
{
// We ran out of input. No match.
break;
}
- // We failed to transition. Upgrade to DFA mode.
- Debug.Assert(currentState.DfaState is not null);
- NfaMatchingState nfaState = perThreadData.NfaState;
- nfaState.InitializeFrom(currentState.DfaState);
- currentState = new CurrentState(nfaState);
+ if (i < inputForInnerLoop.Length)
+ {
+ // We failed to transition. Upgrade to DFA mode.
+ Debug.Assert(currentState.DfaState is not null);
+ NfaMatchingState nfaState = perThreadData.NfaState;
+ nfaState.InitializeFrom(currentState.DfaState);
+ currentState = new CurrentState(nfaState);
+ }
}
// Check for a timeout before continuing.
[MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))]
public async Task Match_Timeout_Repetition_Throws(RegexEngine engine)
{
- if (engine == RegexEngine.NonBacktracking)
- {
- // [ActiveIssue("https://github.com/dotnet/runtime/issues/65991")]
- return;
- }
-
int repetitionCount = 800_000_000;
Regex regex = await RegexHelpers.GetRegexAsync(engine, @"a\s{" + repetitionCount + "}", RegexOptions.None, TimeSpan.FromSeconds(1));
string input = @"a" + new string(' ', repetitionCount) + @"b";