diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index b41add8142..f9e32d91eb 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -305,7 +305,7 @@
https://github.com/dotnet/corefx
00000
-
+
https://github.com/dotnet/corefx
00000
diff --git a/eng/Versions.props b/eng/Versions.props
index d7bd40e97a..e7d82c184c 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -29,7 +29,7 @@
4.6.0-preview4.19156.2
4.7.0-preview4.19156.2
4.6.0-preview4.19156.2
- 4.6.0-preview4.19127.11
+ 4.6.0-preview4.19156.2
4.6.0-preview4.19156.2
4.6.0-preview4.19156.2
1.7.0-preview4.19156.2
diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs
index 963fd5d85c..4f7a15826d 100644
--- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs
+++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs
@@ -323,6 +323,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return;
}
+ // Assigned this before calculating the chunk size since that can throw
+ examined = reader.Position;
+
var chunkSize = CalculateChunkSize(ch1, 0);
ch1 = ch2;
@@ -360,6 +363,9 @@ 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);
}
diff --git a/src/Servers/Kestrel/Core/test/MessageBodyTests.cs b/src/Servers/Kestrel/Core/test/MessageBodyTests.cs
index 785097ab17..bd11ad9d81 100644
--- a/src/Servers/Kestrel/Core/test/MessageBodyTests.cs
+++ b/src/Servers/Kestrel/Core/test/MessageBodyTests.cs
@@ -198,6 +198,94 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
}
+ [Fact]
+ public async Task BadChunkPrefixThrowsBadRequestException()
+ {
+ using (var input = new TestInput())
+ {
+ var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders { HeaderTransferEncoding = "chunked" }, input.Http1Connection);
+ var mockBodyControl = new Mock();
+ mockBodyControl.Setup(m => m.AllowSynchronousIO).Returns(true);
+ var reader = new HttpRequestPipeReader();
+ var stream = new HttpRequestStream(mockBodyControl.Object, reader);
+ reader.StartAcceptingReads(body);
+ var buffer = new byte[1024];
+ var task = stream.ReadAsync(buffer, 0, buffer.Length);
+
+ input.Add("g");
+ input.Add("g");
+
+ await Assert.ThrowsAsync(() => task);
+
+ await body.StopAsync();
+ }
+ }
+
+ [Fact]
+ public async Task WritingChunkOverMaxChunkSizeThrowsBadRequest()
+ {
+ using (var input = new TestInput())
+ {
+ var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders { HeaderTransferEncoding = "chunked" }, input.Http1Connection);
+ var mockBodyControl = new Mock();
+ mockBodyControl.Setup(m => m.AllowSynchronousIO).Returns(true);
+ var reader = new HttpRequestPipeReader();
+ var stream = new HttpRequestStream(mockBodyControl.Object, reader);
+ reader.StartAcceptingReads(body);
+ var buffer = new byte[1024];
+ var task = stream.ReadAsync(buffer, 0, buffer.Length);
+
+ // Max is 10 bytes
+ for (int i = 0; i < 11; i++)
+ {
+ input.Add(i.ToString());
+ }
+
+ await Assert.ThrowsAsync(() => task);
+
+ await body.StopAsync();
+ }
+ }
+
+ [Fact]
+ public async Task InvalidChunkSuffixThrowsBadRequest()
+ {
+ using (var input = new TestInput())
+ {
+ var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders { HeaderTransferEncoding = "chunked" }, input.Http1Connection);
+ var mockBodyControl = new Mock();
+ mockBodyControl.Setup(m => m.AllowSynchronousIO).Returns(true);
+ var reader = new HttpRequestPipeReader();
+ var stream = new HttpRequestStream(mockBodyControl.Object, reader);
+ reader.StartAcceptingReads(body);
+ var buffer = new byte[1024];
+
+ async Task ReadAsync()
+ {
+ while (true)
+ {
+ await stream.ReadAsync(buffer, 0, buffer.Length);
+ }
+ }
+
+ var task = ReadAsync();
+
+ input.Add("1");
+ input.Add("\r");
+ input.Add("\n");
+ input.Add("h");
+ input.Add("0");
+ input.Add("\r");
+ input.Add("\n");
+ input.Add("\r");
+ input.Add("n");
+
+ await Assert.ThrowsAsync(() => task);
+
+ await body.StopAsync();
+ }
+ }
+
[Fact]
public async Task CanReadAsyncFromChunkedEncoding()
{