8076641: getNextEntry throws ArrayIndexOutOfBoundsException when unzipping file
authorsherman
Mon, 06 Apr 2015 13:41:10 -0700
changeset 29815 a50c9d80a80f
parent 29748 9ad0fcf27b36
child 29816 43ad6bf3975b
8076641: getNextEntry throws ArrayIndexOutOfBoundsException when unzipping file Summary: to add extra sanity check for entry extra data Reviewed-by: alanb
jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java
jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
jdk/test/java/util/zip/TestExtraTime.java
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java	Fri Apr 03 16:37:06 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java	Mon Apr 06 13:41:10 2015 -0700
@@ -481,6 +481,8 @@
                     }
                     break;
                 case EXTID_NTFS:
+                    if (sz < 32) // reserved  4 bytes + tag 2 bytes + size 2 bytes
+                        break;   // m[a|c]time 24 bytes
                     int pos = off + 4;               // reserved 4 bytes
                     if (get16(extra, pos) !=  0x0001 || get16(extra, pos + 2) != 24)
                         break;
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Fri Apr 03 16:37:06 2015 -0700
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Mon Apr 06 13:41:10 2015 -0700
@@ -2271,6 +2271,8 @@
                     }
                     break;
                 case EXTID_NTFS:
+                    if (sz < 32)
+                        break;
                     pos += 4;    // reserved 4 bytes
                     if (SH(extra, pos) !=  0x0001)
                         break;
--- a/jdk/test/java/util/zip/TestExtraTime.java	Fri Apr 03 16:37:06 2015 -0700
+++ b/jdk/test/java/util/zip/TestExtraTime.java	Mon Apr 06 13:41:10 2015 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4759491 6303183 7012868 8015666 8023713 8068790
+ * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641
  * @summary Test ZOS and ZIS timestamp in extra field correctly
  */
 
@@ -40,7 +40,6 @@
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
-
 public class TestExtraTime {
 
     public static void main(String[] args) throws Throwable{
@@ -71,6 +70,7 @@
         }
 
         testNullHandling();
+        testTagOnlyHandling();
         testTimeConversions();
     }
 
@@ -208,4 +208,42 @@
             }
         }
     }
+
+    static void check(ZipEntry ze, byte[] extra) {
+        if (extra != null) {
+            byte[] extra1 = ze.getExtra();
+            if (extra1 == null || extra1.length < extra.length ||
+                !Arrays.equals(Arrays.copyOfRange(extra1,
+                                                  extra1.length - extra.length,
+                                                  extra1.length),
+                               extra)) {
+                throw new RuntimeException("Timestamp: storing extra field failed!");
+            }
+        }
+    }
+
+    static void testTagOnlyHandling() throws Throwable {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] extra = new byte[] { 0x0a, 0, 4, 0, 0, 0, 0, 0 };
+        try (ZipOutputStream zos = new ZipOutputStream(baos)) {
+            ZipEntry ze = new ZipEntry("TestExtraTime.java");
+            ze.setExtra(extra);
+            zos.putNextEntry(ze);
+            zos.write(new byte[] { 1,2 ,3, 4});
+        }
+        try (ZipInputStream zis = new ZipInputStream(
+                 new ByteArrayInputStream(baos.toByteArray()))) {
+            ZipEntry ze = zis.getNextEntry();
+            check(ze, extra);
+        }
+        Path zpath = Paths.get(System.getProperty("test.dir", "."),
+                               "TestExtraTime.zip");
+        Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath);
+        try (ZipFile zf = new ZipFile(zpath.toFile())) {
+            ZipEntry ze = zf.getEntry("TestExtraTime.java");
+            check(ze, extra);
+        } finally {
+            Files.delete(zpath);
+        }
+    }
 }