diff --git a/Directory.Build.props b/Directory.Build.props index 7971a44bf5d..696d9573da3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -25,8 +25,8 @@ - net6.0;net7.0 - net6.0;net7.0 + net6.0;net7.0;net8.0 + net6.0;net7.0;net8.0 net6.0 diff --git a/global.json b/global.json index c282f9982eb..2d1c1a50a7c 100644 --- a/global.json +++ b/global.json @@ -4,7 +4,8 @@ "runtimes": { "dotnet": [ "3.1.5", - "6.0.5" + "6.0.22", + "7.0.11" ] } }, diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/Connection.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/Connection.cs index aefca00ee1a..489697dc8d6 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/Connection.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/Connection.cs @@ -365,6 +365,11 @@ public override void Write(byte[] buffer, int offset, int count) public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { + if (count == 0) + { + return 0; + } + var tcs = new TaskCompletionSource(this); AsyncCompletionResult asyncCompletionResult = Connection.BeginRead(0, Math.Min(count, Connection.AsyncReadBufferSize), TimeoutHelper.FromMilliseconds(ReadTimeout), s_onReadComplete, tcs); @@ -777,7 +782,7 @@ internal static void ValidateBufferBounds(int bufferSize, int offset, int size) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(offset), offset, SR.Format(SR.OffsetExceedsBufferSize, bufferSize))); } - if (size <= 0) + if (size < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(size), size, SR.ValueMustBePositive)); } diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/DetectEofStream.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/DetectEofStream.cs index 1352d8c9541..2ae2b181793 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/DetectEofStream.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/DetectEofStream.cs @@ -24,8 +24,9 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, { return 0; } + int returnValue = await base.ReadAsync(buffer, offset, count, cancellationToken); - if (returnValue == 0) + if (count != 0 && returnValue == 0) { ReceivedEof(); } @@ -49,7 +50,7 @@ public override int Read(byte[] buffer, int offset, int count) return 0; } int returnValue = base.Read(buffer, offset, count); - if (returnValue == 0) + if (count != 0 && returnValue == 0) { ReceivedEof(); } diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/ProducerConsumerStream.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/ProducerConsumerStream.cs index 17440a79ee6..916e7f393c6 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/ProducerConsumerStream.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/ProducerConsumerStream.cs @@ -39,6 +39,11 @@ public override void Flush() public override int Read(byte[] buffer, int offset, int count) { + if (count == 0) + { + return 0; + } + try { return ReadAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); @@ -55,19 +60,24 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, { if (buffer == null) { - throw new ArgumentNullException("buffer"); + throw new ArgumentNullException(nameof(buffer)); } if (offset < 0 || offset > buffer.Length) { - throw new ArgumentOutOfRangeException("offset"); + throw new ArgumentOutOfRangeException(nameof(offset)); } - if (count <= 0 || count > buffer.Length - offset) + if (count < 0 || count > buffer.Length - offset) { - throw new ArgumentOutOfRangeException("count"); + throw new ArgumentOutOfRangeException(nameof(count)); } cancellationToken.ThrowIfCancellationRequested(); + if (count == 0) + { + return 0; + } + // _dataAvail must be set before the disposed check to avoid a race condition // when Dispose is called just after the _disposed check which would result in // ReadAsync never completing. diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SingletonConnectionReader.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SingletonConnectionReader.cs index 4d9be599a44..d71af2dd2f4 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SingletonConnectionReader.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SingletonConnectionReader.cs @@ -295,6 +295,11 @@ private void DecodeSize(byte[] buffer, ref int offset, ref int size) private int ReadCore(byte[] buffer, int offset, int count) { + if (count == 0) + { + return 0; + } + int bytesRead = -1; try { diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SocketConnection.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SocketConnection.cs index e699f2f8398..7b57d234084 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SocketConnection.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/SocketConnection.cs @@ -979,6 +979,12 @@ public virtual AsyncCompletionResult BeginRead(int offset, int size, TimeSpan ti private AsyncCompletionResult BeginReadCore(int offset, int size, TimeSpan timeout, Action callback, object state) { + if (size == 0) + { + _asyncReadSize = 0; + return AsyncCompletionResult.Completed; + } + bool abortRead = true; lock (ThisLock)