From 16903bdecbe1fa11e991e0919860bdeb4209c62a Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 2 Apr 2026 11:48:01 +0100 Subject: [PATCH] clean up shrink stream to ensure correctness --- .../Compressors/Shrink/ShrinkStream.Async.cs | 24 +++------------ .../Compressors/Shrink/ShrinkStream.cs | 30 ++++++------------- .../Default/ShrinkCompressionProvider.cs | 7 +---- 3 files changed, 14 insertions(+), 47 deletions(-) diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.Async.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.Async.cs index ac296434..57342ebe 100644 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.Async.cs +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.Async.cs @@ -2,7 +2,6 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; -using SharpCompress.Common; namespace SharpCompress.Compressors.Shrink; @@ -16,12 +15,7 @@ internal partial class ShrinkStream : Stream CancellationToken cancellationToken = default ) { - var shrinkStream = new ShrinkStream( - stream, - compressionMode, - compressedSize, - uncompressedSize - ); + var shrinkStream = new ShrinkStream(stream, uncompressedSize); await shrinkStream.DecompressAsync(cancellationToken).ConfigureAwait(false); return shrinkStream; } @@ -33,26 +27,16 @@ internal partial class ShrinkStream : Stream return; } - // Read actual compressed data from stream rather than pre-allocating based on the + // Read actual compressed data from the stream rather than pre-allocating based on the // declared compressed size, which may be crafted to cause an OutOfMemoryException. // The stream is already bounded by ReadOnlySubStream in ZipFilePart. using var srcMs = new MemoryStream(); - await inStream.CopyToAsync(srcMs, 81920, cancellationToken).ConfigureAwait(false); + await _inStream.CopyToAsync(srcMs, 81920, cancellationToken).ConfigureAwait(false); var src = srcMs.ToArray(); var srcLen = src.Length; // Decompress synchronously (CPU-bound operation) - var srcUsed = 0; - var dstUsed = 0; - - HwUnshrink.Unshrink( - src, - srcLen, - out srcUsed, - _byteOut, - (int)_uncompressedSize, - out dstUsed - ); + HwUnshrink.Unshrink(src, srcLen, out _, _byteOut, (int)_uncompressedSize, out var dstUsed); _outBytesCount = dstUsed; _decompressed = true; } diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs index a7055e93..b7831f45 100644 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -5,33 +5,23 @@ namespace SharpCompress.Compressors.Shrink; internal partial class ShrinkStream : Stream { - private Stream inStream; + private readonly Stream _inStream; - private long _uncompressedSize; - private byte[] _byteOut; + private readonly long _uncompressedSize; + private readonly byte[] _byteOut; private long _outBytesCount; private bool _decompressed; private long _position; - public ShrinkStream( - Stream stream, - CompressionMode compressionMode, - long compressedSize, - long uncompressedSize - ) + public ShrinkStream(Stream stream, long uncompressedSize) { - inStream = stream; + _inStream = stream; _uncompressedSize = uncompressedSize; _byteOut = new byte[_uncompressedSize]; _outBytesCount = 0L; } - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - } - public override bool CanRead => true; public override bool CanSeek => true; @@ -52,23 +42,21 @@ internal partial class ShrinkStream : Stream { if (!_decompressed) { - // Read actual compressed data from stream rather than pre-allocating based on the + // Read actual compressed data from the stream rather than pre-allocating based on the // declared compressed size, which may be crafted to cause an OutOfMemoryException. // The stream is already bounded by ReadOnlySubStream in ZipFilePart. using var srcMs = new MemoryStream(); - inStream.CopyTo(srcMs); + _inStream.CopyTo(srcMs); var src = srcMs.ToArray(); var srcLen = src.Length; - var srcUsed = 0; - var dstUsed = 0; HwUnshrink.Unshrink( src, srcLen, - out srcUsed, + out _, _byteOut, (int)_uncompressedSize, - out dstUsed + out var dstUsed ); _outBytesCount = dstUsed; _decompressed = true; diff --git a/src/SharpCompress/Providers/Default/ShrinkCompressionProvider.cs b/src/SharpCompress/Providers/Default/ShrinkCompressionProvider.cs index 2e26c7a7..95d0746a 100644 --- a/src/SharpCompress/Providers/Default/ShrinkCompressionProvider.cs +++ b/src/SharpCompress/Providers/Default/ShrinkCompressionProvider.cs @@ -27,12 +27,7 @@ public sealed class ShrinkCompressionProvider : ContextRequiredDecompressionProv { ValidateRequiredSizes(context, "Shrink"); - return new ShrinkStream( - source, - CompressionMode.Decompress, - context.InputSize, - context.OutputSize - ); + return new ShrinkStream(source, context.OutputSize); } public override async ValueTask CreateDecompressStreamAsync(