Use ascii decoding routine that disallows null chars (#1445)

* Use ascii decoding routine that disallows null chars
- GetAsciiString() in newer corefxlab builds allows 0 (which is a valid
ascii char). To avoid future regressions, GetAsciiStringNonNullCharacters()
was added and used in place of GetAsciiString() when interpreting the
request line and headers
- Make GetAsciiStringNonNullCharacters return empty instead of null
This commit is contained in:
David Fowler 2017-03-04 11:26:32 -08:00 committed by GitHub
parent 20f75605ca
commit da763b4873
2 changed files with 29 additions and 7 deletions

View File

@ -1228,7 +1228,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
if (needDecode)
{
// Read raw target before mutating memory.
rawTarget = target.GetAsciiString() ?? string.Empty;
rawTarget = target.GetAsciiStringNonNullCharacters();
// URI was encoded, unescape and then parse as utf8
int pathLength = UrlEncoder.Decode(path, path);
@ -1237,7 +1237,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
else
{
// URI wasn't encoded, parse as ASCII
requestUrlPath = path.GetAsciiString() ?? string.Empty;
requestUrlPath = path.GetAsciiStringNonNullCharacters();
if (query.Length == 0)
{
@ -1247,21 +1247,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
}
else
{
rawTarget = target.GetAsciiString() ?? string.Empty;
rawTarget = target.GetAsciiStringNonNullCharacters();
}
}
var normalizedTarget = PathNormalizer.RemoveDotSegments(requestUrlPath);
if (method != HttpMethod.Custom)
{
Method = HttpUtilities.MethodToString(method) ?? String.Empty;
Method = HttpUtilities.MethodToString(method) ?? string.Empty;
}
else
{
Method = customMethod.GetAsciiString() ?? string.Empty;
Method = customMethod.GetAsciiStringNonNullCharacters();
}
QueryString = query.GetAsciiString() ?? string.Empty;
QueryString = query.GetAsciiStringNonNullCharacters();
RawTarget = rawTarget;
HttpVersion = HttpUtilities.VersionToString(version);
@ -1289,7 +1289,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
{
RejectRequest(RequestRejectionReason.TooManyHeaders);
}
var valueString = value.GetAsciiString() ?? string.Empty;
var valueString = value.GetAsciiStringNonNullCharacters();
FrameRequestHeaders.Append(name, valueString);
}

View File

@ -94,6 +94,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure
}
}
public unsafe static string GetAsciiStringNonNullCharacters(this Span<byte> span)
{
if (span.IsEmpty)
{
return string.Empty;
}
var asciiString = new string('\0', span.Length);
fixed (char* output = asciiString)
fixed (byte* buffer = &span.DangerousGetPinnableReference())
{
// This version if AsciiUtilities returns null if there are any null (0 byte) characters
// in the string
if (!AsciiUtilities.TryGetAsciiString(buffer, output, span.Length))
{
throw new InvalidOperationException();
}
}
return asciiString;
}
public static string GetAsciiStringEscaped(this Span<byte> span, int maxChars)
{
var sb = new StringBuilder();