From 83c80d2c9bf0a50f30b0899d1be1961d6bb7fcc4 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Sat, 15 Aug 2020 12:24:07 +0100 Subject: [PATCH] PR #333: Handle unsupported compression methods in ZipInputStream better MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change ZipInputStream to use its own IsEntryCompressionMethodSupported function rather than the one in ZipEntry. * Unit test for ZipInputStream.CanDecompressEntry being false for AES encrypted entries. * Fix comment typo Co-authored-by: nils måsén --- .../Zip/ZipInputStream.cs | 20 +++++++++-- .../Zip/ZipEncryptionHandling.cs | 34 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs index 147d4043d..66a3fc872 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs @@ -131,10 +131,26 @@ public bool CanDecompressEntry { get { - return (entry != null) && entry.CanDecompress; + return (entry != null) && IsEntryCompressionMethodSupported(entry) && entry.CanDecompress; } } + /// + /// Is the compression method for the specified entry supported? + /// + /// + /// Uses entry.CompressionMethodForHeader so that entries of type WinZipAES will be rejected. + /// + /// the entry to check. + /// true if the compression methiod is supported, false if not. + private static bool IsEntryCompressionMethodSupported(ZipEntry entry) + { + var entryCompressionMethod = entry.CompressionMethodForHeader; + + return entryCompressionMethod == CompressionMethod.Deflated || + entryCompressionMethod == CompressionMethod.Stored; + } + /// /// Advances to the next entry in the archive /// @@ -271,7 +287,7 @@ public ZipEntry GetNextEntry() } // Determine how to handle reading of data if this is attempted. - if (entry.IsCompressionMethodSupported()) + if (IsEntryCompressionMethodSupported(entry)) { internalReader = new ReadDataHandler(InitialRead); } diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs index adb938516..49317207c 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipEncryptionHandling.cs @@ -437,6 +437,40 @@ public void ZipFileAESReadWithEmptyPassword() } } + /// + /// ZipInputStream can't decrypt AES encrypted entries, but it should report that to the caller + /// rather than just failing. + /// + [Test] + [Category("Zip")] + public void ZipinputStreamShouldGracefullyFailWithAESStreams() + { + string password = "password"; + + using (var memoryStream = new MemoryStream()) + { + // Try to create a zip stream + WriteEncryptedZipToStream(memoryStream, password, 256); + + // reset + memoryStream.Seek(0, SeekOrigin.Begin); + + // Try to read + using (var inputStream = new ZipInputStream(memoryStream)) + { + inputStream.Password = password; + var entry = inputStream.GetNextEntry(); + Assert.That(entry.AESKeySize, Is.EqualTo(256), "Test entry should be AES256 encrypted."); + + // CanDecompressEntry should be false. + Assert.That(inputStream.CanDecompressEntry, Is.False, "CanDecompressEntry should be false for AES encrypted entries"); + + // Should throw on read. + Assert.Throws(() => inputStream.ReadByte()); + } + } + } + private static readonly string[] possible7zPaths = new[] { // Check in PATH "7z", "7za",