diff options
Diffstat (limited to 'src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs')
-rw-r--r-- | src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs index 6bc2b7c168..6fb8c2c1e7 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs @@ -288,6 +288,11 @@ public class HttpParser<TRequestHandler> : IHttpParser<TRequestHandler> where TR // This was a multi-line header. Advance the reader. reader.Advance(length); + if (reader.End) + { + return true; + } + continue; } @@ -384,36 +389,51 @@ public class HttpParser<TRequestHandler> : IHttpParser<TRequestHandler> where TR header = currentSlice.Slice(reader.Position, lineEnd); } - var headerSpan = header.ToSpan(); + byte[]? array = null; + int length = (int)header.Length; + Span<byte> span = length <= 256 ? stackalloc byte[length] : array = ArrayPool<byte>.Shared.Rent(length); - // 'a:b\n' or 'a:b\r\n' - var minHeaderSpan = _disableHttp1LineFeedTerminators ? 5 : 4; - if (headerSpan.Length < minHeaderSpan) + try { - RejectRequestHeader(headerSpan); - } + header.CopyTo(span); + span = span.Slice(0, length); - var terminatorSize = -1; + // 'a:b\n' or 'a:b\r\n' + var minHeaderSpan = _disableHttp1LineFeedTerminators ? 5 : 4; + if (span.Length < minHeaderSpan) + { + RejectRequestHeader(span); + } - if (headerSpan[^1] == ByteLF) - { - if (headerSpan[^2] == ByteCR) + var terminatorSize = -1; + + if (span[^1] == ByteLF) { - terminatorSize = 2; + if (span[^2] == ByteCR) + { + terminatorSize = 2; + } + else if (!_disableHttp1LineFeedTerminators) + { + terminatorSize = 1; + } } - else if (!_disableHttp1LineFeedTerminators) + + // Last chance to bail if the terminator size is not valid or the header doesn't parse. + if (terminatorSize == -1 || !TryTakeSingleHeader(handler, span.Slice(0, span.Length - terminatorSize))) { - terminatorSize = 1; + RejectRequestHeader(span); } - } - // Last chance to bail if the terminator size is not valid or the header doesn't parse. - if (terminatorSize == -1 || !TryTakeSingleHeader(handler, headerSpan.Slice(0, headerSpan.Length - terminatorSize))) + return span.Length; + } + finally { - RejectRequestHeader(headerSpan); + if (array is not null) + { + ArrayPool<byte>.Shared.Return(array); + } } - - return headerSpan.Length; } private static bool TryTakeSingleHeader(TRequestHandler handler, ReadOnlySpan<byte> headerLine) |