Skip to content

Commit bf6b70e

Browse files
committed
Throw exception on Store+Descriptor entries
1 parent c814877 commit bf6b70e

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/ICSharpCode.SharpZipLib/Zip/ZipInputStream.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,14 @@ private int ReadingNotSupported(byte[] destination, int offset, int count)
493493
throw new ZipException("The compression method for this entry is not supported");
494494
}
495495

496+
/// <summary>
497+
/// Handle attempts to read from this entry by throwing an exception
498+
/// </summary>
499+
private int StoredDescriptorEntry(byte[] destination, int offset, int count) =>
500+
throw new StreamUnsupportedException(
501+
"The combination of Stored compression method and Descriptor flag is not possible to read using ZipInputStream");
502+
503+
496504
/// <summary>
497505
/// Perform the initial read on an entry which may include
498506
/// reading encryption headers and setting up inflation.
@@ -544,13 +552,22 @@ private int InitialRead(byte[] destination, int offset, int count)
544552
inputBuffer.CryptoTransform = null;
545553
}
546554

547-
if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0))
555+
var usesDescriptor = (flags & (int) GeneralBitFlags.Descriptor) != 0;
556+
557+
if ((csize > 0) || usesDescriptor)
548558
{
549559
if ((method == CompressionMethod.Deflated) && (inputBuffer.Available > 0))
550560
{
551561
inputBuffer.SetInflaterInput(inf);
552562
}
553563

564+
// It's not possible to know how many bytes to read when using "Stored" compression (unless using encryption)
565+
if (!entry.IsCrypted && method == CompressionMethod.Stored && usesDescriptor)
566+
{
567+
internalReader = StoredDescriptorEntry;
568+
return StoredDescriptorEntry(destination, offset, count);
569+
}
570+
554571
internalReader = new ReadDataHandler(BodyRead);
555572
return BodyRead(destination, offset, count);
556573
}

test/ICSharpCode.SharpZipLib.Tests/Zip/StreamHandling.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,5 +520,41 @@ public void AddingAnAESEntryWithNoPasswordShouldThrow()
520520
}
521521
}
522522
}
523+
524+
[Test]
525+
[Category("Zip")]
526+
public void ShouldThrowDescriptiveExceptionOnUncompressedDescriptorEntry()
527+
{
528+
using (var ms = new MemoryStreamWithoutSeek())
529+
{
530+
using (var zos = new ZipOutputStream(ms))
531+
{
532+
zos.IsStreamOwner = false;
533+
var entry = new ZipEntry("testentry");
534+
entry.CompressionMethod = CompressionMethod.Stored;
535+
entry.Flags |= (int)GeneralBitFlags.Descriptor;
536+
zos.PutNextEntry(entry);
537+
zos.Write(new byte[1], 0, 1);
538+
zos.CloseEntry();
539+
}
540+
541+
// Patch the Compression Method, since ZipOutputStream automatically changes it to Deflate when descriptors are used
542+
ms.Seek(8, SeekOrigin.Begin);
543+
ms.WriteByte((byte)CompressionMethod.Stored);
544+
ms.Seek(0, SeekOrigin.Begin);
545+
546+
using (var zis = new ZipInputStream(ms))
547+
{
548+
zis.IsStreamOwner = false;
549+
var buf = new byte[32];
550+
zis.GetNextEntry();
551+
552+
Assert.Throws(typeof(StreamUnsupportedException), () =>
553+
{
554+
zis.Read(buf, 0, buf.Length);
555+
});
556+
}
557+
}
558+
}
523559
}
524560
}

0 commit comments

Comments
 (0)