diff options
author | Chris Ross <Tratcher@Outlook.com> | 2022-10-04 23:06:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-04 23:06:09 +0300 |
commit | 1c61e0c849309f5e69340417fea0095c3079e45a (patch) | |
tree | 740c77168bd48ee002aa92943810953dda776f2f | |
parent | c5e3e52496e24f928a1c23b7723b0a1749c6c9cc (diff) |
Allow zero byte reads on the test server response body #41692 (#44020)
-rw-r--r-- | src/Hosting/TestHost/src/ResponseBodyReaderStream.cs | 18 | ||||
-rw-r--r-- | src/Hosting/TestHost/test/ResponseBodyTests.cs | 34 |
2 files changed, 35 insertions, 17 deletions
diff --git a/src/Hosting/TestHost/src/ResponseBodyReaderStream.cs b/src/Hosting/TestHost/src/ResponseBodyReaderStream.cs index b715ee0229..04d419fd39 100644 --- a/src/Hosting/TestHost/src/ResponseBodyReaderStream.cs +++ b/src/Hosting/TestHost/src/ResponseBodyReaderStream.cs @@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.TestHost public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - VerifyBuffer(buffer, offset, count); + ValidateBufferArguments(buffer, offset, count); CheckAborted(); if (_readerComplete) @@ -101,22 +101,6 @@ namespace Microsoft.AspNetCore.TestHost return (int)actual; } - private static void VerifyBuffer(byte[] buffer, int offset, int count) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - if (offset < 0 || offset > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(offset), offset, string.Empty); - } - if (count <= 0 || count > buffer.Length - offset) - { - throw new ArgumentOutOfRangeException(nameof(count), count, string.Empty); - } - } - internal void Cancel() { Abort(new OperationCanceledException()); diff --git a/src/Hosting/TestHost/test/ResponseBodyTests.cs b/src/Hosting/TestHost/test/ResponseBodyTests.cs index 8c0c572d81..51bb15eedc 100644 --- a/src/Hosting/TestHost/test/ResponseBodyTests.cs +++ b/src/Hosting/TestHost/test/ResponseBodyTests.cs @@ -122,6 +122,40 @@ namespace Microsoft.AspNetCore.TestHost.Tests Assert.Equal(contentBytes, responseBytes); } + [Fact] + public async Task BodyStream_ZeroByteRead_Success() + { + var emptyReadStarted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + var contentBytes = new byte[] { 32 }; + using var host = await CreateHost(async httpContext => + { + await httpContext.Response.Body.WriteAsync(contentBytes); + await emptyReadStarted.Task; + await httpContext.Response.Body.WriteAsync(contentBytes); + }); + + var client = host.GetTestServer().CreateClient(); + var response = await client.GetAsync("/", HttpCompletionOption.ResponseHeadersRead); + var stream = await response.Content.ReadAsStreamAsync(); + var bytes = new byte[5]; + var read = await stream.ReadAsync(bytes); + Assert.Equal(1, read); + Assert.Equal(contentBytes[0], bytes[0]); + + // This will chain to the Memory overload, but that does less restrictive validation on the input. + // https://github.com/dotnet/aspnetcore/issues/41692#issuecomment-1248714684 + var zeroByteRead = stream.ReadAsync(Array.Empty<byte>(), 0, 0); + Assert.False(zeroByteRead.IsCompleted); + emptyReadStarted.SetResult(); + read = await zeroByteRead; + Assert.Equal(0, read); + + read = await stream.ReadAsync(bytes); + Assert.Equal(1, read); + Assert.Equal(contentBytes[0], bytes[0]); + } + private Task<IHost> CreateHost(RequestDelegate appDelegate) { return new HostBuilder() |