Blame SOURCES/jdk8186464-rh1433262-zip64_failure.patch

723393
# HG changeset patch
723393
# User sherman
723393
# Date 1505950914 25200
723393
#      Wed Sep 20 16:41:54 2017 -0700
723393
# Node ID 723486922bfe4c17e3f5c067ce5e97229842fbcd
723393
# Parent  c8ac05bbe47771b3dafa2e7fc9a95d86d68d7c07
723393
8186464: ZipFile cannot read some InfoZip ZIP64 zip files
723393
Reviewed-by: martin
723393
723393
diff --git openjdk.orig/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java openjdk/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
723393
--- openjdk.orig/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
723393
+++ openjdk/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
723393
@@ -93,6 +93,7 @@
723393
     private final boolean createNew;     // create a new zip if not exists
723393
     private static final boolean isWindows =
723393
         System.getProperty("os.name").startsWith("Windows");
723393
+    private final boolean forceEnd64;
723393
 
723393
     ZipFileSystem(ZipFileSystemProvider provider,
723393
                   Path zfpath,
723393
@@ -109,12 +110,13 @@
723393
         if (this.defaultDir.charAt(0) != '/')
723393
             throw new IllegalArgumentException("default dir should be absolute");
723393
 
723393
+        this.forceEnd64 = "true".equals(env.get("forceZIP64End"));
723393
         this.provider = provider;
723393
         this.zfpath = zfpath;
723393
         if (Files.notExists(zfpath)) {
723393
             if (createNew) {
723393
                 try (OutputStream os = Files.newOutputStream(zfpath, CREATE_NEW, WRITE)) {
723393
-                    new END().write(os, 0);
723393
+                    new END().write(os, 0, forceEnd64);
723393
                 }
723393
             } else {
723393
                 throw new FileSystemNotFoundException(zfpath.toString());
723393
@@ -1011,28 +1013,36 @@
723393
                     end.cenoff = ENDOFF(buf);
723393
                     end.comlen = ENDCOM(buf);
723393
                     end.endpos = pos + i;
723393
-                    if (end.cenlen == ZIP64_MINVAL ||
723393
-                        end.cenoff == ZIP64_MINVAL ||
723393
-                        end.centot == ZIP64_MINVAL32)
723393
-                    {
723393
-                        // need to find the zip64 end;
723393
-                        byte[] loc64 = new byte[ZIP64_LOCHDR];
723393
-                        if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
723393
-                            != loc64.length) {
723393
-                            return end;
723393
-                        }
723393
-                        long end64pos = ZIP64_LOCOFF(loc64);
723393
-                        byte[] end64buf = new byte[ZIP64_ENDHDR];
723393
-                        if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
723393
-                            != end64buf.length) {
723393
-                            return end;
723393
-                        }
723393
-                        // end64 found, re-calcualte everything.
723393
-                        end.cenlen = ZIP64_ENDSIZ(end64buf);
723393
-                        end.cenoff = ZIP64_ENDOFF(end64buf);
723393
-                        end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
723393
-                        end.endpos = end64pos;
723393
+                    // try if there is zip64 end;
723393
+                    byte[] loc64 = new byte[ZIP64_LOCHDR];
723393
+                    if (end.endpos < ZIP64_LOCHDR ||
723393
+                        readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
723393
+                        != loc64.length ||
723393
+                        !locator64SigAt(loc64, 0)) {
723393
+                        return end;
723393
+                    }
723393
+                    long end64pos = ZIP64_LOCOFF(loc64);
723393
+                    byte[] end64buf = new byte[ZIP64_ENDHDR];
723393
+                    if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
723393
+                        != end64buf.length ||
723393
+                        !end64SigAt(end64buf, 0)) {
723393
+                        return end;
723393
                     }
723393
+                    // end64 found,
723393
+                    long cenlen64 = ZIP64_ENDSIZ(end64buf);
723393
+                    long cenoff64 = ZIP64_ENDOFF(end64buf);
723393
+                    long centot64 = ZIP64_ENDTOT(end64buf);
723393
+                    // double-check
723393
+                    if (cenlen64 != end.cenlen && end.cenlen != ZIP64_MINVAL ||
723393
+                        cenoff64 != end.cenoff && end.cenoff != ZIP64_MINVAL ||
723393
+                        centot64 != end.centot && end.centot != ZIP64_MINVAL32) {
723393
+                        return end;
723393
+                    }
723393
+                    // to use the end64 values
723393
+                    end.cenlen = cenlen64;
723393
+                    end.cenoff = cenoff64;
723393
+                    end.centot = (int)centot64; // assume total < 2g
723393
+                    end.endpos = end64pos;
723393
                     return end;
723393
                 }
723393
             }
723393
@@ -1198,7 +1208,7 @@
723393
 
723393
     // sync the zip file system, if there is any udpate
723393
     private void sync() throws IOException {
723393
-        //System.out.printf("->sync(%s) starting....!%n", toString());
723393
+        // System.out.printf("->sync(%s) starting....!%n", toString());
723393
         // check ex-closer
723393
         if (!exChClosers.isEmpty()) {
723393
             for (ExChannelCloser ecc : exChClosers) {
723393
@@ -1289,7 +1299,7 @@
723393
             }
723393
             end.centot = elist.size();
723393
             end.cenlen = written - end.cenoff;
723393
-            end.write(os, written);
723393
+            end.write(os, written, forceEnd64);
723393
         }
723393
         if (!streams.isEmpty()) {
723393
             //
723393
@@ -1727,8 +1737,8 @@
723393
         long endpos;
723393
         int disktot;
723393
 
723393
-        void write(OutputStream os, long offset) throws IOException {
723393
-            boolean hasZip64 = false;
723393
+        void write(OutputStream os, long offset, boolean forceEnd64) throws IOException {
723393
+            boolean hasZip64 = forceEnd64; // false;
723393
             long xlen = cenlen;
723393
             long xoff = cenoff;
723393
             if (xlen >= ZIP64_MINVAL) {
723393
@@ -1753,8 +1763,8 @@
723393
                 writeShort(os, 45);               // version needed to extract
723393
                 writeInt(os, 0);                  // number of this disk
723393
                 writeInt(os, 0);                  // central directory start disk
723393
-                writeLong(os, centot);            // number of directory entires on disk
723393
-                writeLong(os, centot);            // number of directory entires
723393
+                writeLong(os, centot);            // number of directory entries on disk
723393
+                writeLong(os, centot);            // number of directory entries
723393
                 writeLong(os, cenlen);            // length of central directory
723393
                 writeLong(os, cenoff);            // offset of central directory
723393
 
723393
diff --git a/src/share/native/javopenjdk.orig/jdk/util/zip/zip_util.c openjdk/jdk/src/share/native/java/util/zip/zip_util.c
723393
--- openjdk.orig/jdk/src/share/native/java/util/zip/zip_util.c
723393
+++ openjdk/jdk/src/share/native/java/util/zip/zip_util.c
723393
@@ -383,6 +383,9 @@
723393
 {
723393
     char loc64[ZIP64_LOCHDR];
723393
     jlong end64pos;
723393
+    if (endpos < ZIP64_LOCHDR) {
723393
+	return -1;
723393
+    }
723393
     if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) {
723393
         return -1;    // end64 locator not found
723393
     }
723393
@@ -545,6 +548,7 @@
723393
 {
723393
     /* Following are unsigned 32-bit */
723393
     jlong endpos, end64pos, cenpos, cenlen, cenoff;
723393
+    jlong cenlen64, cenoff64, centot64;
723393
     /* Following are unsigned 16-bit */
723393
     jint total, tablelen, i, j;
723393
     unsigned char *cenbuf = NULL;
723393
@@ -572,13 +576,20 @@
723393
     cenlen = ENDSIZ(endbuf);
723393
     cenoff = ENDOFF(endbuf);
723393
     total  = ENDTOT(endbuf);
723393
-    if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL ||
723393
-        total == ZIP64_MAGICCOUNT) {
723393
-        unsigned char end64buf[ZIP64_ENDHDR];
723393
-        if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
723393
-            cenlen = ZIP64_ENDSIZ(end64buf);
723393
-            cenoff = ZIP64_ENDOFF(end64buf);
723393
-            total = (jint)ZIP64_ENDTOT(end64buf);
723393
+    unsigned char end64buf[ZIP64_ENDHDR];
723393
+    if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
723393
+	// end64 candidate found,
723393
+	cenlen64 = ZIP64_ENDSIZ(end64buf);
723393
+	cenoff64 = ZIP64_ENDOFF(end64buf);
723393
+	centot64 = ZIP64_ENDTOT(end64buf);
723393
+	// double-check
723393
+	if ((cenlen64 == cenlen || cenlen == ZIP64_MAGICVAL) &&
723393
+	    (cenoff64 == cenoff || cenoff == ZIP64_MAGICVAL) &&
723393
+	    (centot64 == total || total == ZIP64_MAGICCOUNT)) {
723393
+	    // to use the end64 values
723393
+            cenlen = cenlen64;
723393
+            cenoff = cenoff64;
723393
+            total = (jint)centot64;
723393
             endpos = end64pos;
723393
             endhdrlen = ZIP64_ENDHDR;
723393
         }
723393
diff --git a/test/javopenjdk.orig/jdk/util/zip/ZipFile/ReadZip.java openjdk/jdk/test/java/util/zip/ZipFile/ReadZip.java
723393
--- openjdk.orig/jdk/test/java/util/zip/ZipFile/ReadZip.java
723393
+++ openjdk/jdk/test/java/util/zip/ZipFile/ReadZip.java
723393
@@ -22,7 +22,7 @@
723393
  */
723393
 
723393
 /* @test
723393
- * @bug 4241361 4842702 4985614 6646605 5032358 6923692 6233323 8144977 8184993
723393
+ * @bug 4241361 4842702 4985614 6646605 5032358 6923692 6233323 8144977 8184993 8186464
723393
  * @summary Make sure we can read a zip file.
aef6f0
    @key randomness
723393
  * @run main/othervm ReadZip
723393
@@ -30,12 +30,24 @@
723393
  */
723393
 
723393
 import java.io.*;
723393
+import java.net.URI;
723393
 import java.nio.file.Files;
723393
+import java.nio.file.FileSystem;
723393
+import java.nio.file.FileSystems;
723393
+import java.nio.file.Path;
723393
 import java.nio.file.Paths;
723393
 import java.nio.file.StandardCopyOption;
723393
 import java.nio.file.StandardOpenOption;
723393
+import java.util.Collections;
723393
+import java.util.HashMap;
723393
+import java.util.List;
723393
+import java.util.Map;
723393
 import java.util.zip.*;
723393
 
723393
+import sun.misc.IOUtils;
723393
+
723393
+import static java.nio.charset.StandardCharsets.US_ASCII;
723393
+
723393
 public class ReadZip {
723393
     private static void unreached (Object o)
723393
         throws Exception
723393
@@ -143,8 +155,6 @@
723393
             newZip.delete();
723393
         }
723393
 
723393
-
723393
-
723393
         // Throw a FNF exception when read a non-existing zip file
723393
         try { unreached (new ZipFile(
723393
                              new File(System.getProperty("test.src", "."),
723393
@@ -152,5 +162,54 @@
723393
                                       + String.valueOf(new java.util.Random().nextInt())
723393
                                       + ".zip")));
723393
         } catch (FileNotFoundException fnfe) {}
723393
+
723393
+        // read a zip file with ZIP64 end
723393
+        Path path = Paths.get(System.getProperty("test.dir", ""), "end64.zip");
723393
+        try {
723393
+            URI uri = URI.create("jar:" + path.toUri());
723393
+            Map<String, Object> env = new HashMap<>();
723393
+	    env.put("create", "true");
723393
+	    env.put("forceZIP64End", "true");
723393
+            try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
723393
+                Files.write(fs.getPath("hello"), "hello".getBytes());
723393
+            }
723393
+            try (ZipFile zf = new ZipFile(path.toFile())) {
723393
+                if (!"hello".equals(new String(IOUtils.readAllBytes(zf.getInputStream(new ZipEntry("hello"))),
723393
+                                               US_ASCII)))
723393
+                    throw new RuntimeException("zipfile: read entry failed");
723393
+            } catch (IOException x) {
723393
+                throw new RuntimeException("zipfile: zip64 end failed");
723393
+            }
723393
+            try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
723393
+                if (!"hello".equals(new String(Files.readAllBytes(fs.getPath("hello")))))
723393
+                    throw new RuntimeException("zipfs: read entry failed");
723393
+            } catch (IOException x) {
723393
+                throw new RuntimeException("zipfile: zip64 end failed");
723393
+            }
723393
+        } finally {
723393
+            Files.deleteIfExists(path);
723393
+        }
723393
+
723393
+        // read a zip file created via "echo hello | zip dst.zip -", which uses
723393
+        // ZIP64 end record
723393
+        if (Files.notExists(Paths.get("/usr/bin/zip")))
723393
+            return;
723393
+        try {
723393
+            Process zip = new ProcessBuilder("zip", path.toString().toString(), "-").start();
723393
+            OutputStream os = zip.getOutputStream();
723393
+            os.write("hello".getBytes(US_ASCII));
723393
+            os.close();
723393
+            zip.waitFor();
723393
+            if (zip.exitValue() == 0 && Files.exists(path)) {
723393
+                try (ZipFile zf = new ZipFile(path.toFile())) {
723393
+                    if (!"hello".equals(new String(IOUtils.readAllBytes(zf.getInputStream(new ZipEntry("-"))))))
723393
+                        throw new RuntimeException("zipfile: read entry failed");
723393
+                } catch (IOException x) {
723393
+                    throw new RuntimeException("zipfile: zip64 end failed");
723393
+                }
723393
+            }
723393
+        } finally {
723393
+            Files.deleteIfExists(path);
723393
+        }
723393
     }
723393
 }