diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs
index 66a3fc872..5a0e8e4ac 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.
@@ -544,13 +552,22 @@ private int InitialRead(byte[] destination, int offset, int count)
inputBuffer.CryptoTransform = null;
}
- if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0))
+ var usesDescriptor = (flags & (int) GeneralBitFlags.Descriptor) != 0;
+
+ if ((csize > 0) || usesDescriptor)
{
if ((method == CompressionMethod.Deflated) && (inputBuffer.Available > 0))
{
inputBuffer.SetInflaterInput(inf);
}
+ // It's not possible to know how many bytes to read when using "Stored" compression (unless using encryption)
+ if (!entry.IsCrypted && method == CompressionMethod.Stored && usesDescriptor)
+ {
+ 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);
+ });
+ }
+ }
+ }
}
}