From 46023fc8530a25734d1744591f5be8fe5ed122ef Mon Sep 17 00:00:00 2001 From: Quinn Damerell Date: Tue, 2 Apr 2024 10:02:15 -0700 Subject: [PATCH 1/3] Adding logic to the Deflator and Inflator streams to free byte buffers on Dispose. --- .../Streams/DeflaterOutputStream.cs | 2 ++ .../Streams/InflaterInputStream.cs | 26 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs index a7e6807ca..fb03f003c 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -432,6 +432,8 @@ protected override void Dispose(bool disposing) baseOutputStream_.Dispose(); } } + + buffer_ = null; } } diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs index 980ffc701..5f282e36a 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs @@ -11,7 +11,7 @@ namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams /// /// The buffer supports decryption of incoming data. /// - public class InflaterInputBuffer + public class InflaterInputBuffer : IDisposable { #region Constructors @@ -269,6 +269,25 @@ public long ReadLeLong() return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); } + /// + /// Implements the dispose method of the interface. + /// + public void Dispose() + { + if(rawData != null) + { + rawData = null; + } + if(clearText != null) + { + clearText = null; + } + if(internalClearText != null) + { + internalClearText = null; + } + } + /// /// Get/set the to apply to any data. /// @@ -637,6 +656,11 @@ protected override void Dispose(bool disposing) InflaterPool.Instance.Return(inflater); } inf = null; + + if(inputBuffer != null) + { + inputBuffer.Dispose(); + } } /// From b1935f0c3eb7c4dc8ad34dd28220c1f565143ac7 Mon Sep 17 00:00:00 2001 From: Quinn Damerell Date: Tue, 2 Apr 2024 10:16:47 -0700 Subject: [PATCH 2/3] Adding logic to use shared array pool buffer to allocate buffers. --- .../Streams/DeflaterOutputStream.cs | 22 ++++++++++++++- .../Streams/InflaterInputStream.cs | 28 +++++++++++-------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs index fb03f003c..ff1d1bbdc 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -1,5 +1,6 @@ using ICSharpCode.SharpZipLib.Encryption; using System; +using System.Buffers; using System.IO; using System.Security.Cryptography; using System.Text; @@ -83,7 +84,16 @@ public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int buff } baseOutputStream_ = baseOutputStream; - buffer_ = new byte[bufferSize]; + + if(ArrayPool.Shared != null) + { + buffer_ = ArrayPool.Shared.Rent(bufferSize); + isBufferOwnedByArrayPool_ = true; + } + else + { + buffer_ = new byte[bufferSize]; + } deflater_ = deflater ?? throw new ArgumentNullException(nameof(deflater)); } @@ -433,6 +443,11 @@ protected override void Dispose(bool disposing) } } + // Ensure buffer is returned to the pool if it was rented from it. + if(isBufferOwnedByArrayPool_) + { + ArrayPool.Shared.Return(buffer_); + } buffer_ = null; } } @@ -542,6 +557,11 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc /// private byte[] buffer_; + /// + /// If true, this buffer is owned by the array pool and should be returned there on Dispose. + /// + private bool isBufferOwnedByArrayPool_; + /// /// The deflater which is used to deflate the stream. /// diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs index 5f282e36a..39e79a501 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.IO; using System.Security.Cryptography; using ICSharpCode.SharpZipLib.Core; @@ -36,7 +37,16 @@ public InflaterInputBuffer(Stream stream, int bufferSize) { bufferSize = 1024; } - rawData = new byte[bufferSize]; + + if(ArrayPool.Shared != null) + { + rawData = ArrayPool.Shared.Rent(bufferSize); + isRawDataOwnedByArrayPool = true; + } + else + { + rawData = new byte[bufferSize]; + } clearText = rawData; } @@ -274,18 +284,13 @@ public long ReadLeLong() /// public void Dispose() { - if(rawData != null) - { - rawData = null; - } - if(clearText != null) - { - clearText = null; - } - if(internalClearText != null) + if(isRawDataOwnedByArrayPool) { - internalClearText = null; + ArrayPool.Shared.Return(rawData); } + rawData = null; + clearText = null; + internalClearText = null; } /// @@ -325,6 +330,7 @@ public ICryptoTransform CryptoTransform private int rawLength; private byte[] rawData; + private bool isRawDataOwnedByArrayPool = false; private int clearTextLength; private byte[] clearText; From d1fef8d5a18fe3fb738b9b3c6430f084896a928b Mon Sep 17 00:00:00 2001 From: Quinn Damerell Date: Tue, 2 Apr 2024 10:19:41 -0700 Subject: [PATCH 3/3] Minor update. --- .../Zip/Compression/Streams/DeflaterOutputStream.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs index ff1d1bbdc..08c61b574 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -236,7 +236,10 @@ public Encoding ZipCryptoEncoding { /// protected void EncryptBlock(byte[] buffer, int offset, int length) { - if(cryptoTransform_ is null) return; + if(cryptoTransform_ is null) + { + return; + } cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); }