Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8178069

PackTestZip64 fails incorrectly with ZipException when system zlib is used.

XMLWordPrintable

      When using an alternative zlib implementation (in my case the implementation at https://github.com/jtkukunas/zlib) jdk/test/tools/pack200PackTestZip64.java test fails incorrectly.

      The test fails with following exception:
      java.util.zip.ZipException: invalid entry compressed size (expected 88 but got 89 bytes)
          at java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:267)
          at java.util.zip.ZipOutputStream.putNextEntry(ZipOutputStream.java:192)
          at java.util.jar.JarOutputStream.putNextEntry(JarOutputStream.java:109)
          at PackTestZip64.generateLargeJar(PackTestZip64.java:137)
          at PackTestZip64.testPacking(PackTestZip64.java:55)
          at PackTestZip64.main(PackTestZip64.java:43)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:497)
          at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:110)
          at java.lang.Thread.run(Thread.java:745)
                      
      Here is what happens :
      The test generates a new jar file ( in generateLargeJar()) from existing files in golden.jar along with a large number of small dummy files.
      Since the JarEntry's which are put in the new jar are read from the existing jar, the compressed size for them is set.
      Here is the relevant code in generateLargeJar() -
                      for (JarEntry je : Collections.list(srcJar.entries())) {
                          copyTo.putNextEntry(je);
                          if (!je.isDirectory()) {
                              copyStream(srcJar.getInputStream(je), copyTo);
                          }
                          copyTo.closeEntry();
                      }
      Later ZipOutputStream.closeEntry() validates the compressed size in the JarEntry by comparing it to number of bytes written,
                      if (e.csize != def.getBytesWritten()) {
                          throw new ZipException(
                              "invalid entry compressed size (expected " +
                              e.csize + " but got " + def.getBytesWritten() + " bytes)");
                      }

      The above check fails, throwing an exception.
      This is an error because the Zlib specification gives implementations a flexibility of choosing a string search algorithm, thus generating different bit streams.
      A workaround is to reset the compressed size of 'JarEntry' before its added to the new jar, as shown below,
                     je.setCompressedSize(-1);
                     copyTo.putNextEntry(je);

            Unassigned Unassigned
            kkharbas Kishor Kharbas (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: