diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs index 12f41c5740b8cb..92716b8c913200 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs @@ -334,7 +334,7 @@ public override int Read(byte[] buffer, int offset, int count) if (_superStream.Position != _positionInSuperStream) _superStream.Seek(_positionInSuperStream, SeekOrigin.Begin); if (_positionInSuperStream + count > _endInSuperStream) - count = (int)(_endInSuperStream - _positionInSuperStream); + count = (int)Math.Max(0L, _endInSuperStream - _positionInSuperStream); Debug.Assert(count >= 0); Debug.Assert(count <= origCount); @@ -357,7 +357,7 @@ public override int Read(Span destination) if (_superStream.Position != _positionInSuperStream) _superStream.Seek(_positionInSuperStream, SeekOrigin.Begin); if (_positionInSuperStream + count > _endInSuperStream) - count = (int)(_endInSuperStream - _positionInSuperStream); + count = (int)Math.Max(0L, _endInSuperStream - _positionInSuperStream); Debug.Assert(count >= 0); Debug.Assert(count <= origCount); @@ -395,7 +395,7 @@ async ValueTask Core(Memory buffer, CancellationToken cancellationTok if (_positionInSuperStream > _endInSuperStream - buffer.Length) { - buffer = buffer.Slice(0, (int)(_endInSuperStream - _positionInSuperStream)); + buffer = buffer.Slice(0, (int)Math.Max(0L, _endInSuperStream - _positionInSuperStream)); } int ret = await _superStream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); diff --git a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs index 5218765645a3a7..c2f856dd88bf96 100644 --- a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs +++ b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_ReadTests.cs @@ -889,5 +889,35 @@ public static async Task CompressionMethod_Deflate64_ReturnsDeflate64(bool async Assert.Equal(ZipCompressionMethod.Deflate64, readEntry.CompressionMethod); await DisposeZipArchive(async, readArchive); } + + [Theory] + [MemberData(nameof(Get_Booleans_Data))] + public static async Task ReadAfterSeekingPastEnd_ReturnsZeroBytes(bool async) + { + using var ms = new MemoryStream(); + using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, leaveOpen: true)) + { + var entry = archive.CreateEntry("test.txt", CompressionLevel.NoCompression); + using var stream = entry.Open(); + stream.Write("Hello, World!"u8); + } + + ms.Position = 0; + using var readArchive = await CreateZipArchive(async, ms, ZipArchiveMode.Read); + Stream readStream = await OpenEntryStream(async, readArchive.Entries[0]); + + readStream.Seek(1, SeekOrigin.End); + Assert.Equal(14, readStream.Position); + + byte[] buffer = new byte[1024]; + int bytesRead = async + ? await readStream.ReadAsync(buffer) + : readStream.Read(buffer, 0, buffer.Length); + + Assert.Equal(0, bytesRead); + Assert.Equal(14, readStream.Position); + + await DisposeStream(async, readStream); + } } }