Repository: commons-compress Updated Branches: refs/heads/master a12adc362 -> c66db899c
COMPRESS-436 sanity check compressed size is known for bzip etc Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/c66db899 Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/c66db899 Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/c66db899 Branch: refs/heads/master Commit: c66db899cb061c79934986f0efa19a50ca33703f Parents: a12adc3 Author: Stefan Bodewig <bode...@apache.org> Authored: Sun Jan 14 12:12:50 2018 +0100 Committer: Stefan Bodewig <bode...@apache.org> Committed: Sun Jan 14 12:12:50 2018 +0100 ---------------------------------------------------------------------- src/changes/changes.xml | 4 ++++ .../zip/UnsupportedZipFeatureException.java | 7 +++++++ .../archivers/zip/ZipArchiveInputStream.java | 21 ++++++++++++++++++-- .../zip/ZipArchiveInputStreamTest.java | 16 +++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-compress/blob/c66db899/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e9b8d7a..46c9b56 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -97,6 +97,10 @@ The <action> type attribute can be add,update,fix,remove. <action issue="COMPRESS-437" type="add" date="2018-01-13"> Added read-only DEFLATE64 support to 7z archives. </action> + <action issue="COMPRESS-436" type="update" date="2018-01-14"> + Added a few extra sanity checks for the rarer compression + methods used in ZIP archives. + </action> </release> <release version="1.15" date="2017-10-17" description="Release 1.15 http://git-wip-us.apache.org/repos/asf/commons-compress/blob/c66db899/src/main/java/org/apache/commons/compress/archivers/zip/UnsupportedZipFeatureException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/UnsupportedZipFeatureException.java b/src/main/java/org/apache/commons/compress/archivers/zip/UnsupportedZipFeatureException.java index 5d7bfc4..a92f9c7 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/UnsupportedZipFeatureException.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/UnsupportedZipFeatureException.java @@ -112,6 +112,13 @@ public class UnsupportedZipFeatureException extends ZipException { * @since 1.5 */ public static final Feature SPLITTING = new Feature("splitting"); + /** + * The archive contains entries with unknown compressed size + * for a compression method that doesn't support detection of + * the end of the compressed stream. + * @since 1.16 + */ + public static final Feature UNKNOWN_COMPRESSED_SIZE = new Feature("unknown compressed size"); private final String name; http://git-wip-us.apache.org/repos/asf/commons-compress/blob/c66db899/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java index 755c7c7..41e6940 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java @@ -412,8 +412,8 @@ public class ZipArchiveInputStream extends ArchiveInputStream { if (ae instanceof ZipArchiveEntry) { final ZipArchiveEntry ze = (ZipArchiveEntry) ae; return ZipUtil.canHandleEntryData(ze) - && supportsDataDescriptorFor(ze); - + && supportsDataDescriptorFor(ze) + && supportsCompressedSizeFor(ze); } return false; } @@ -438,6 +438,10 @@ public class ZipArchiveInputStream extends ArchiveInputStream { throw new UnsupportedZipFeatureException(UnsupportedZipFeatureException.Feature.DATA_DESCRIPTOR, current.entry); } + if (!supportsCompressedSizeFor(current.entry)) { + throw new UnsupportedZipFeatureException(UnsupportedZipFeatureException.Feature.UNKNOWN_COMPRESSED_SIZE, + current.entry); + } int read; if (current.entry.getMethod() == ZipArchiveOutputStream.STORED) { @@ -804,6 +808,19 @@ public class ZipArchiveInputStream extends ArchiveInputStream { } /** + * Whether the compressed size for the entry is either known or + * not required by the compression method being used. + */ + private boolean supportsCompressedSizeFor(final ZipArchiveEntry entry) { + return entry.getCompressedSize() != ArchiveEntry.SIZE_UNKNOWN + || entry.getMethod() == ZipEntry.DEFLATED + || entry.getMethod() == ZipMethod.ENHANCED_DEFLATED.getCode() + || (entry.getGeneralPurposeBit().usesDataDescriptor() + && allowStoredEntriesWithDataDescriptor + && entry.getMethod() == ZipEntry.STORED); + } + + /** * Caches a stored entry that uses the data descriptor. * * <ul> http://git-wip-us.apache.org/repos/asf/commons-compress/blob/c66db899/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java index 853d6c8..5d1cdb1 100644 --- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java @@ -21,10 +21,12 @@ package org.apache.commons.compress.archivers.zip; import static org.apache.commons.compress.AbstractTestCase.getFile; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; @@ -324,6 +326,20 @@ public class ZipArchiveInputStreamTest { ZipArchiveEntry.NameSource.NAME_WITH_EFS_FLAG); } + @Test + public void properlyMarksEntriesAsUnreadableIfUncompressedSizeIsUnknown() throws Exception { + // we never read any data + try (ZipArchiveInputStream zis = new ZipArchiveInputStream(new ByteArrayInputStream(new byte[0]))) { + ZipArchiveEntry e = new ZipArchiveEntry("test"); + e.setMethod(ZipMethod.DEFLATED.getCode()); + assertTrue(zis.canReadEntryData(e)); + e.setMethod(ZipMethod.ENHANCED_DEFLATED.getCode()); + assertTrue(zis.canReadEntryData(e)); + e.setMethod(ZipMethod.BZIP2.getCode()); + assertFalse(zis.canReadEntryData(e)); + } + } + private static byte[] readEntry(ZipArchiveInputStream zip, ZipArchiveEntry zae) throws IOException { final int len = (int)zae.getSize(); final byte[] buff = new byte[len];