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

JarFile constructor throws undocumented java.nio.file.InvalidPathException

XMLWordPrintable

    • b15
    • x86
    • os_x

        ADDITIONAL SYSTEM INFORMATION :
        openjdk version "11" 2018-09-25
        OpenJDK Runtime Environment 18.9 (build 11+28)
        OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

        A DESCRIPTION OF THE PROBLEM :
        This was raised in the OpenJDK core-libs-dev mailing list and was acknowledged as a bug http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-October/055859.html. Although the discussion started off as a Windows OS specific issue, later in that thread, Alan rightly pointed out that this isn't Windows specific. Details of the bug are as follows:

        Please consider the following trivial code:

        import java.util.jar.*;
        import java.io.*;

        public class JarFileTest {
            public static void main(final String[] args) throws Exception {
                final String tmpDir = System.getProperty("java.io.tmpdir");
                try {
                    final JarFile jarFile = new JarFile(tmpDir + File.separator
        + "*");
                } catch (IOException ioe) {
                    System.out.println("Got the expected IOException " + ioe);
                }
            }
        }

        The constructor of the JarFile is passed a string which intentionally is
        an (wildcard) invalid path. The above code (as expected) throws an
        IOException on *nix systems across various version of Java (tested
        against Java 8, 11). The same code throws an IOException (as expected)
        in Java 8 on Windows OS too. However, in Java 11, on Windows OS, this
        code throws a different exception (java.nio.file.InvalidPathException)
        which isn't IOException or a subclass of it:

        Exception in thread "main" java.nio.file.InvalidPathException: Illegal
        char <*> at index 38: C:\Users\someone\AppData\Local\Temp\1\*
        at
        java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
        at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
        at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
        at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
        at
        java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:229)
        at java.base/java.io.File.toPath(File.java:2290)
        at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1220)
        at
        java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:727)
        at java.base/java.util.zip.ZipFile$CleanableResource.get(ZipFile.java:845)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:245)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:175)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:341)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:312)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:251)
        at JarFileTest.main(JarFileTest.java:8)


        The javadoc of JarFile constructor(s) mentions that:

             * @throws IOException if an I/O error has occurred

        Given that the javadoc doesn't mention anything about this other
        exception, would this throwing of java.nio.file.InvalidPathException be
        considered a bug in the implementation?

        If this indeed is considered a bug, it appears to be the code in
        java.util.zip.ZipFile$Source.get method which calls File#toPath(), which
        as per its javadoc is indeed expected to throw an
        java.nio.file.InvalidPathException if a Path cannot be constructed out
        of the File. Looking at the implementation of the underlying
        java.nio.file.FileSystem on *nix and Windows, they differ when it comes
        to whether or not the exception gets thrown (Unix one seems to always
        return a result). But keeping the implementation of
        java.nio.file.FileSystem aside, I guess the
        java.util.zip.ZipFile$Source.get code needs to have a catch block for
        the InvalidPathException to wrap that into a IOException? Something like:


        # HG changeset patch
        # User Jaikiran Pai <jaikiran.pai@gmail.com>
        # Date 1538645309 -19800
        # Thu Oct 04 14:58:29 2018 +0530
        # Node ID ff1bfd8cc9a3b385716fa5191bb68989d552f87e
        # Parent 8705c6d536c5c197d0210acccf145ebc48f90227
        Wrap and throw an IOException when a InvalidPathException is thrown

        diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java
        b/src/java.base/share/classes/java/util/zip/ZipFile.java
        --- a/src/java.base/share/classes/java/util/zip/ZipFile.java
        +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
        @@ -35,6 +35,7 @@
         import java.lang.ref.Cleaner.Cleanable;
         import java.nio.charset.Charset;
         import java.nio.charset.StandardCharsets;
        +import java.nio.file.InvalidPathException;
         import java.nio.file.attribute.BasicFileAttributes;
         import java.nio.file.Files;
         import java.util.ArrayDeque;
        @@ -1218,8 +1219,13 @@
         
         
                 static Source get(File file, boolean toDelete) throws IOException {
        - Key key = new Key(file,
        - Files.readAttributes(file.toPath(),
        BasicFileAttributes.class));
        + final Key key;
        + try {
        + key = new Key(file,
        + Files.readAttributes(file.toPath(),
        BasicFileAttributes.class));
        + } catch (InvalidPathException ipe) {
        + throw new IOException(ipe);
        + }
                     Source src;
                     synchronized (files) {
                         src = files.get(key);


        Any thoughts?






        REGRESSION : Last worked in version 8u172

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        A java.io.IOException is expected to be thrown from the JarFIle constructor
        ACTUAL -
        A java.nio.file.InvalidPathException is thrown instead

        ---------- BEGIN SOURCE ----------
        For Windows OS:

        import java.util.jar.*;
        import java.io.*;

        public class JarFileTest {
        public static void main(final String[] args) throws Exception {
        final String tmpDir = System.getProperty("java.io.tmpdir");
        try {
        final JarFile jarFile = new JarFile(tmpDir + File.separator + "*");
        } catch (IOException ioe) {
        System.out.println("Got the expected IOException " + ioe);
        }
        }
        }


        For *nix OS:

        import java.util.jar.*;
        import java.io.*;

        public class JarFileTest {
        public static void main(final String[] args) throws Exception {
        final String tmpDir = System.getProperty("java.io.tmpdir");
        try {
        final JarFile jarFile = new JarFile(tmpDir + File.separator + "abc\0xyz");
        } catch (IOException ioe) {
        System.out.println("Got the expected IOException " + ioe);
        }
        }
        }
        ---------- END SOURCE ----------

        FREQUENCY : always


              lancea Lance Andersen
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: