diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs index 4f7a15826d..2189bc4419 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs @@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http return; } - // Assigned this before calculating the chunk size since that can throw + // Advance examined before possibly throwing, so we don't risk examining less than the previous call to ParseChunkedPrefix. examined = reader.Position; var chunkSize = CalculateChunkSize(ch1, 0); @@ -348,10 +348,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http return; } + // Advance examined before possibly throwing, so we don't risk examining less than the previous call to ParseChunkedPrefix. + examined = reader.Position; + if (ch1 == '\r' && ch2 == '\n') { consumed = reader.Position; - examined = reader.Position; AddAndCheckConsumedBytes(reader.Consumed); _inputLength = chunkSize; @@ -363,9 +365,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http ch1 = ch2; } - // Set examined so that we capture the progress that way made - examined = reader.Position; - // At this point, 10 bytes have been consumed which is enough to parse the max value "7FFFFFFF\r\n". BadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData); } @@ -453,10 +452,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http var suffixBuffer = buffer.Slice(0, 2); var suffixSpan = suffixBuffer.ToSpan(); + + // Advance examined before possibly throwing, so we don't risk examining less than the previous call to ParseChunkedSuffix. + examined = suffixBuffer.End; + if (suffixSpan[0] == '\r' && suffixSpan[1] == '\n') { consumed = suffixBuffer.End; - examined = suffixBuffer.End; AddAndCheckConsumedBytes(2); _mode = Mode.Prefix; } @@ -480,10 +482,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http var trailerBuffer = buffer.Slice(0, 2); var trailerSpan = trailerBuffer.ToSpan(); + // Advance examined before possibly throwing, so we don't risk examining less than the previous call to ParseChunkedTrailer. + examined = trailerBuffer.End; + if (trailerSpan[0] == '\r' && trailerSpan[1] == '\n') { consumed = trailerBuffer.End; - examined = trailerBuffer.End; AddAndCheckConsumedBytes(2); _mode = Mode.Complete; }