diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java index 563f6491c615df7b75f1cfe62948a4abf63bd4ec..c8c733df81dd4b2e7772ed6568b91113bc94b470 100644 --- a/luni/src/main/java/java/util/zip/ZipEntry.java +++ b/luni/src/main/java/java/util/zip/ZipEntry.java @@ -357,7 +357,13 @@ public class ZipEntry implements ZipConstants, Cloneable { throw new ZipException("Central Directory Entry not found"); } - it.seek(10); + it.seek(8); + int gpbf = it.readShort(); + + if ((gpbf & ~ZipFile.GPBF_SUPPORTED_MASK) != 0) { + throw new ZipException("Invalid General Purpose Bit Flag: " + gpbf); + } + compressionMethod = it.readShort(); time = it.readShort(); modDate = it.readShort(); diff --git a/luni/src/main/java/java/util/zip/ZipFile.java b/luni/src/main/java/java/util/zip/ZipFile.java index 172141c0161ce251424aff4a88b07c43030db53f..3e750f4ae3869845747e5b73d2f8e236c2ed8c6f 100644 --- a/luni/src/main/java/java/util/zip/ZipFile.java +++ b/luni/src/main/java/java/util/zip/ZipFile.java @@ -67,6 +67,12 @@ public class ZipFile implements ZipConstants { */ static final int GPBF_UTF8_FLAG = 1 << 11; + /** + * Supported General Purpose Bit Flags Mask. + * Bit mask of supported GPBF bits. + */ + static final int GPBF_SUPPORTED_MASK = GPBF_DATA_DESCRIPTOR_FLAG | GPBF_UTF8_FLAG; + /** * Open zip file for reading. */ @@ -242,11 +248,19 @@ public class ZipFile implements ZipConstants { RandomAccessFile localRaf = raf; synchronized (localRaf) { // We don't know the entry data's start position. All we have is the - // position of the entry's local header. At position 28 we find the - // length of the extra data. In some cases this length differs from - // the one coming in the central header. - RAFStream rafStream = new RAFStream(localRaf, entry.localHeaderRelOffset + 28); + // position of the entry's local header. At position 6 we find the + // General Purpose Bit Flag. + // http://www.pkware.com/documents/casestudies/APPNOTE.TXT + RAFStream rafStream= new RAFStream(localRaf, entry.localHeaderRelOffset + 6); DataInputStream is = new DataInputStream(rafStream); + int gpbf = Short.reverseBytes(is.readShort()); + if ((gpbf & ~ZipFile.GPBF_SUPPORTED_MASK) != 0) { + throw new ZipException("Invalid General Purpose Bit Flag: " + gpbf); + } + + // At position 28 we find the length of the extra data. In some cases + // this length differs from the one coming in the central header. + is.skipBytes(20); int localExtraLenOrWhatever = Short.reverseBytes(is.readShort()); is.close(); diff --git a/luni/src/main/java/java/util/zip/ZipInputStream.java b/luni/src/main/java/java/util/zip/ZipInputStream.java index 97aa35023d3e70577d7931616cb056a11bb25c3b..0135e1e10795d0e923840b7cabfe2fb7cc3defa0 100644 --- a/luni/src/main/java/java/util/zip/ZipInputStream.java +++ b/luni/src/main/java/java/util/zip/ZipInputStream.java @@ -237,6 +237,10 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants throw new ZipException("Cannot read local header version " + version); } int flags = peekShort(LOCFLG - LOCVER); + if ((flags & ~ZipFile.GPBF_SUPPORTED_MASK) != 0) { + throw new ZipException("Invalid General Purpose Bit Flag: " + flags); + } + hasDD = ((flags & ZipFile.GPBF_DATA_DESCRIPTOR_FLAG) != 0); int ceLastModifiedTime = peekShort(LOCTIM - LOCVER); int ceLastModifiedDate = peekShort(LOCTIM - LOCVER + 2);