Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Optimize recursion of System.Net.Http.HttpRuleParser.GetExpressionLength #35959

Merged
merged 3 commits into from
Mar 14, 2019
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 28 additions & 38 deletions src/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,12 @@ internal static int GetHostLength(string input, int startIndex, bool allowToken,

internal static HttpParseResult GetCommentLength(string input, int startIndex, out int length)
{
int nestedCount = 0;
return GetExpressionLength(input, startIndex, '(', ')', true, ref nestedCount, out length);
return GetExpressionLength(input, startIndex, '(', ')', true, 1, out length);
}

internal static HttpParseResult GetQuotedStringLength(string input, int startIndex, out int length)
{
int nestedCount = 0;
return GetExpressionLength(input, startIndex, '"', '"', false, ref nestedCount, out length);
return GetExpressionLength(input, startIndex, '"', '"', false, 1, out length);
}

// quoted-pair = "\" CHAR
Expand Down Expand Up @@ -360,7 +358,7 @@ internal static HttpParseResult GetQuotedPairLength(string input, int startIndex
// comments, resulting in a stack overflow exception. In addition having more than 1 nested comment (if any)
// is unusual.
private static HttpParseResult GetExpressionLength(string input, int startIndex, char openChar,
char closeChar, bool supportsNesting, ref int nestedCount, out int length)
char closeChar, bool supportsNesting, int nestedCount, out int length)
{
Debug.Assert(input != null);
Debug.Assert((startIndex >= 0) && (startIndex < input.Length));
Expand Down Expand Up @@ -393,43 +391,35 @@ private static HttpParseResult GetExpressionLength(string input, int startIndex,
// If we support nested expressions and we find an open-char, then parse the nested expressions.
if (supportsNesting && (input[current] == openChar))
{
nestedCount++;
try
// Check if we exceeded the number of nested calls.
if (nestedCount > maxNestedCount)
MarcoRossignoli marked this conversation as resolved.
Show resolved Hide resolved
{
// Check if we exceeded the number of nested calls.
if (nestedCount > maxNestedCount)
{
return HttpParseResult.InvalidFormat;
}
return HttpParseResult.InvalidFormat;
}

int nestedLength = 0;
HttpParseResult nestedResult = GetExpressionLength(input, current, openChar, closeChar,
supportsNesting, ref nestedCount, out nestedLength);
int nestedLength = 0;
HttpParseResult nestedResult = GetExpressionLength(input, current, openChar, closeChar,
supportsNesting, nestedCount + 1, out nestedLength);

switch (nestedResult)
{
case HttpParseResult.Parsed:
current += nestedLength; // Add the length of the nested expression and continue.
break;

case HttpParseResult.NotParsed:
Debug.Fail("'NotParsed' is unexpected: We started nested expression " +
"parsing, because we found the open-char. So either it's a valid nested " +
"expression or it has invalid format.");
break;

case HttpParseResult.InvalidFormat:
// If the nested expression is invalid, we can't continue, so we fail with invalid format.
return HttpParseResult.InvalidFormat;

default:
Debug.Fail("Unknown enum result: " + nestedResult);
break;
}
}
finally
switch (nestedResult)
{
nestedCount--;
case HttpParseResult.Parsed:
current += nestedLength; // Add the length of the nested expression and continue.
break;

case HttpParseResult.NotParsed:
Debug.Fail("'NotParsed' is unexpected: We started nested expression " +
"parsing, because we found the open-char. So either it's a valid nested " +
"expression or it has invalid format.");
break;

case HttpParseResult.InvalidFormat:
// If the nested expression is invalid, we can't continue, so we fail with invalid format.
return HttpParseResult.InvalidFormat;

default:
Debug.Fail("Unknown enum result: " + nestedResult);
break;
}

// after nested call we continue with parsing
Expand Down