From fc203706c88fdf2064daa3512f976de58fe2e873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Sat, 3 Oct 2020 15:07:38 +0200 Subject: [PATCH] Throw exception on Store+Descriptor entries --- .../Zip/ZipInputStream.cs | 15 ++++++++ .../Zip/StreamHandling.cs | 36 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs index 66a3fc872..936e1148f 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs @@ -493,6 +493,14 @@ private int ReadingNotSupported(byte[] destination, int offset, int count) throw new ZipException("The compression method for this entry is not supported"); } + /// + /// Handle attempts to read from this entry by throwing an exception + /// + private int StoredDescriptorEntry(byte[] destination, int offset, int count) => + throw new StreamUnsupportedException( + "The combination of Stored compression method and Descriptor flag is not possible to read using ZipInputStream"); + + /// /// Perform the initial read on an entry which may include /// reading encryption headers and setting up inflation. @@ -551,6 +559,13 @@ private int InitialRead(byte[] destination, int offset, int count) inputBuffer.SetInflaterInput(inf); } + // It's not possible to know how many bytes to read when using "Stored" compression + if (method == CompressionMethod.Stored) + { + internalReader = StoredDescriptorEntry; + return StoredDescriptorEntry(destination, offset, count); + } + internalReader = new ReadDataHandler(BodyRead); return BodyRead(destination, offset, count); } diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/StreamHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/StreamHandling.cs index cb2c72d16..a946e3954 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Zip/StreamHandling.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/StreamHandling.cs @@ -502,5 +502,41 @@ public void ShouldBeAbleToReadEntriesWithInvalidFileNames() } } } + + [Test] + [Category("Zip")] + public void ShouldThrowDescriptiveExceptionOnUncompressedDescriptorEntry() + { + using (var ms = new MemoryStreamWithoutSeek()) + { + using (var zos = new ZipOutputStream(ms)) + { + zos.IsStreamOwner = false; + var entry = new ZipEntry("testentry"); + entry.CompressionMethod = CompressionMethod.Stored; + entry.Flags |= (int)GeneralBitFlags.Descriptor; + zos.PutNextEntry(entry); + zos.Write(new byte[1], 0, 1); + zos.CloseEntry(); + } + + // Patch the Compression Method, since ZipOutputStream automatically changes it to Deflate when descriptors are used + ms.Seek(8, SeekOrigin.Begin); + ms.WriteByte((byte)CompressionMethod.Stored); + ms.Seek(0, SeekOrigin.Begin); + + using (var zis = new ZipInputStream(ms)) + { + zis.IsStreamOwner = false; + var buf = new byte[32]; + zis.GetNextEntry(); + + Assert.Throws(typeof(StreamUnsupportedException), () => + { + zis.Read(buf, 0, buf.Length); + }); + } + } + } } }