diff --git a/src/Http/Routing/src/Matching/DfaMatcher.cs b/src/Http/Routing/src/Matching/DfaMatcher.cs index b39ca762a9..dc9a3a7b43 100644 --- a/src/Http/Routing/src/Matching/DfaMatcher.cs +++ b/src/Http/Routing/src/Matching/DfaMatcher.cs @@ -228,13 +228,14 @@ namespace Microsoft.AspNetCore.Routing.Matching { for (var i = 0; i < captures.Length; i++) { - var parameterName = captures[i].parameterName; - if (segments.Length > captures[i].segmentIndex) + (var parameterName, var segmentIndex, var slotIndex) = captures[i]; + + if ((uint)segmentIndex < (uint)segments.Length) { - var segment = segments[captures[i].segmentIndex]; + var segment = segments[segmentIndex]; if (parameterName != null && segment.Length > 0) { - slots[captures[i].slotIndex] = new KeyValuePair( + slots[slotIndex] = new KeyValuePair( parameterName, path.Substring(segment.Start, segment.Length)); } @@ -249,7 +250,7 @@ namespace Microsoft.AspNetCore.Routing.Matching ReadOnlySpan segments) { // Read segmentIndex to local both to skip double read from stack value - // and to use the same in-bounds validated varaible to access the array. + // and to use the same in-bounds validated variable to access the array. var segmentIndex = catchAll.segmentIndex; if ((uint)segmentIndex < (uint)segments.Length) { @@ -271,7 +272,7 @@ namespace Microsoft.AspNetCore.Routing.Matching { (var complexSegment, var segmentIndex) = complexSegments[i]; var segment = segments[segmentIndex]; - var text = path.Substring(segment.Start, segment.Length); + var text = path.AsSpan(segment.Start, segment.Length); if (!RoutePatternMatcher.MatchComplexSegment(complexSegment, text, values)) { Logger.CandidateRejectedByComplexSegment(_logger, path, endpoint, complexSegment); diff --git a/src/Http/Routing/src/Patterns/RoutePatternMatcher.cs b/src/Http/Routing/src/Patterns/RoutePatternMatcher.cs index 7f90c882af..bb35818703 100644 --- a/src/Http/Routing/src/Patterns/RoutePatternMatcher.cs +++ b/src/Http/Routing/src/Patterns/RoutePatternMatcher.cs @@ -160,7 +160,7 @@ namespace Microsoft.AspNetCore.Routing } if (!pathSegment.IsSimple) { - if (!MatchComplexSegment(pathSegment, requestSegment.ToString(), values)) + if (!MatchComplexSegment(pathSegment, requestSegment.AsSpan(), values)) { return false; } @@ -292,7 +292,7 @@ namespace Microsoft.AspNetCore.Routing internal static bool MatchComplexSegment( RoutePatternPathSegment routeSegment, - string requestSegment, + ReadOnlySpan requestSegment, RouteValueDictionary values) { var indexOfLastSegment = routeSegment.Parts.Count - 1; @@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Routing private static bool MatchComplexSegmentCore( RoutePatternPathSegment routeSegment, - string requestSegment, + ReadOnlySpan requestSegment, RouteValueDictionary values, int indexOfLastSegmentUsed) { @@ -366,14 +366,14 @@ namespace Microsoft.AspNetCore.Routing Debug.Assert(part.IsLiteral || part.IsSeparator); lastLiteral = part; - var startIndex = lastIndex - 1; + var startIndex = lastIndex; // If we have a pending parameter subsegment, we must leave at least one character for that if (parameterNeedsValue != null) { startIndex--; } - if (startIndex < 0) + if (startIndex == 0) { return false; } @@ -382,17 +382,15 @@ namespace Microsoft.AspNetCore.Routing if (part.IsLiteral) { var literal = (RoutePatternLiteralPart)part; - indexOfLiteral = requestSegment.LastIndexOf( + indexOfLiteral = requestSegment.Slice(0, startIndex).LastIndexOf( literal.Content, - startIndex, StringComparison.OrdinalIgnoreCase); } else { var literal = (RoutePatternSeparatorPart)part; - indexOfLiteral = requestSegment.LastIndexOf( + indexOfLiteral = requestSegment.Slice(0, startIndex).LastIndexOf( literal.Content, - startIndex, StringComparison.OrdinalIgnoreCase); } @@ -465,9 +463,9 @@ namespace Microsoft.AspNetCore.Routing } } - var parameterValueString = requestSegment.Substring(parameterStartIndex, parameterTextLength); + var parameterValueSpan = requestSegment.Slice(parameterStartIndex, parameterTextLength); - if (string.IsNullOrEmpty(parameterValueString)) + if (parameterValueSpan.Length == 0) { // If we're here that means we have a segment that contains multiple sub-segments. // For these segments all parameters must have non-empty values. If the parameter @@ -478,7 +476,7 @@ namespace Microsoft.AspNetCore.Routing else { // If there's a value in the segment for this parameter, use the subsegment value - outValues.Add(parameterNeedsValue.Name, parameterValueString); + outValues.Add(parameterNeedsValue.Name, new string(parameterValueSpan)); } parameterNeedsValue = null;