From 99ab19fedbd7c78e1564a56a9b26b45460d964f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Thu, 20 Oct 2022 11:05:17 +0200 Subject: [PATCH 1/2] test: add test for issue #782 --- .../Tar/TarInputStreamTests.cs | 28 +++++++++++++++++++ .../TestSupport/Utils.cs | 17 ++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs index 83457834f..0a8d08f6e 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs @@ -1,9 +1,13 @@ using System; +using System.Buffers; +using System.Drawing; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; +using ICSharpCode.SharpZipLib.GZip; using ICSharpCode.SharpZipLib.Tar; +using ICSharpCode.SharpZipLib.Tests.TestSupport; using NUnit.Framework; namespace ICSharpCode.SharpZipLib.Tests.Tar @@ -87,5 +91,29 @@ public async Task TestReadAsync() Assert.AreEqual(975, read3); Assert.AreEqual(entryBytes.AsSpan(1025, 975).ToArray(), buffer.AsSpan().Slice(0, 975).ToArray()); } + + [Test] + public void ReadEmptyStreamWhenArrayPoolIsDirty() + { + // Rent an array with the same size as the tar buffer from the array pool + var buffer = ArrayPool.Shared.Rent(TarBuffer.DefaultRecordSize); + + // Fill the array with anything but 0 + Utils.FillArray(buffer, 0x8b); + + // Return the now dirty buffer to the array pool + ArrayPool.Shared.Return(buffer); + + Assert.DoesNotThrow(() => + { + using var inStream = new MemoryStream(Array.Empty()); + // using var gzipStream = new GZipInputStream(inStream); + using var tarInputStream = new TarInputStream(inStream, Encoding.UTF8); + // using var tarInputStream = new TarInputStream(gzipStream, Encoding.UTF8); + while (tarInputStream.GetNextEntry() is { } tarEntry) + { + } + }, "reading from an empty input stream should not cause an error"); + } } } diff --git a/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Utils.cs b/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Utils.cs index f610660ee..ca1838500 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Utils.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/TestSupport/Utils.cs @@ -133,6 +133,15 @@ public static void PatchFirstEntrySize(Stream stream, int newSize) stream.Write(sizeBytes, 0, 4); } } + + public static void FillArray(byte[] buffer, byte value) + { +#if NET6_0_OR_GREATER + Array.Fill(buffer, value); +#else + for(var i = 0; i < buffer.Length; i++) buffer[i] = value; +#endif + } } public class TestTraceListener : TraceListener @@ -185,7 +194,7 @@ internal TempFile(string dirPath = null, string filename = null) _fileInfo = new FileInfo(Path.Combine(dirPath, filename)); } - #region IDisposable Support +#region IDisposable Support private bool _disposed; // To detect redundant calls @@ -213,7 +222,7 @@ public void Dispose() GC.SuppressFinalize(this); } - #endregion IDisposable Support +#endregion IDisposable Support } @@ -245,7 +254,7 @@ public TempFile CreateDummyFile(string name, int size = 16, int seed = Utils.Def public TempFile GetFile(string fileName) => new TempFile(FullPath, fileName); - #region IDisposable Support +#region IDisposable Support private bool _disposed; // To detect redundant calls @@ -272,6 +281,6 @@ public void Dispose() GC.SuppressFinalize(this); } - #endregion IDisposable Support +#endregion IDisposable Support } } From 12cc7bec74f70b8f556df234a823d7a92bfa5766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Thu, 20 Oct 2022 11:22:37 +0200 Subject: [PATCH 2/2] fix(tar): clear rest of buffer when eof is reached --- src/ICSharpCode.SharpZipLib/Tar/TarBuffer.cs | 5 +++++ .../Tar/TarInputStreamTests.cs | 8 ++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Tar/TarBuffer.cs b/src/ICSharpCode.SharpZipLib/Tar/TarBuffer.cs index 2cef01c52..b987f1ce0 100644 --- a/src/ICSharpCode.SharpZipLib/Tar/TarBuffer.cs +++ b/src/ICSharpCode.SharpZipLib/Tar/TarBuffer.cs @@ -402,6 +402,11 @@ private async ValueTask ReadRecordAsync(CancellationToken ct, bool isAsync // if (numBytes <= 0) { + // Fill the rest of the buffer with 0 to clear any left over data in the shared buffer + for (; offset < RecordSize; offset++) + { + recordBuffer[offset] = 0; + } break; } diff --git a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs index 0a8d08f6e..fb5a26714 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs @@ -1,11 +1,9 @@ using System; using System.Buffers; -using System.Drawing; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; -using ICSharpCode.SharpZipLib.GZip; using ICSharpCode.SharpZipLib.Tar; using ICSharpCode.SharpZipLib.Tests.TestSupport; using NUnit.Framework; @@ -106,10 +104,8 @@ public void ReadEmptyStreamWhenArrayPoolIsDirty() Assert.DoesNotThrow(() => { - using var inStream = new MemoryStream(Array.Empty()); - // using var gzipStream = new GZipInputStream(inStream); - using var tarInputStream = new TarInputStream(inStream, Encoding.UTF8); - // using var tarInputStream = new TarInputStream(gzipStream, Encoding.UTF8); + using var emptyStream = new MemoryStream(Array.Empty()); + using var tarInputStream = new TarInputStream(emptyStream, Encoding.UTF8); while (tarInputStream.GetNextEntry() is { } tarEntry) { }