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 83457834f..fb5a26714 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarInputStreamTests.cs @@ -1,9 +1,11 @@ using System; +using System.Buffers; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.Tar; +using ICSharpCode.SharpZipLib.Tests.TestSupport; using NUnit.Framework; namespace ICSharpCode.SharpZipLib.Tests.Tar @@ -87,5 +89,27 @@ 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 emptyStream = new MemoryStream(Array.Empty()); + using var tarInputStream = new TarInputStream(emptyStream, 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 } }