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