8216553: JrtFIleSystemProvider getPath(URI) omits /modules element from file path
authorsundar
Tue, 28 May 2019 19:30:30 +0530
changeset 55057 63ab89cc3e69
parent 55056 146f257274c9
child 55059 0422b4b5cb8e
8216553: JrtFIleSystemProvider getPath(URI) omits /modules element from file path Reviewed-by: alanb, jlaskey
src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java
src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
test/jdk/jdk/internal/jrtfs/Basic.java
test/langtools/tools/lib/toolbox/JarTask.java
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java	Tue May 28 14:53:57 2019 +0200
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java	Tue May 28 19:30:30 2019 +0530
@@ -190,10 +190,10 @@
             throw new IllegalArgumentException("Fragment component present");
         }
         String path = uri.getPath();
-        if (path == null || path.charAt(0) != '/') {
+        if (path == null || path.charAt(0) != '/' || path.contains("..")) {
             throw new IllegalArgumentException("Invalid path component");
         }
-        return getTheFileSystem().getPath(path);
+        return getTheFileSystem().getPath("/modules" + path);
     }
 
     private FileSystem getTheFileSystem() {
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java	Tue May 28 14:53:57 2019 +0200
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java	Tue May 28 19:30:30 2019 +0530
@@ -25,6 +25,7 @@
 package jdk.internal.jrtfs;
 
 import java.io.File;
+import java.io.IOError;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -170,7 +171,16 @@
     @Override
     public final URI toUri() {
         try {
-            return new URI("jrt", toAbsolutePath().path, null);
+            String p = toAbsolutePath().path;
+            if (!p.startsWith("/modules") || p.contains("..")) {
+                throw new IOError(new RuntimeException(p + " cannot be represented as URI"));
+            }
+
+            p = p.substring("/modules".length());
+            if (p.isEmpty()) {
+                p = "/";
+            }
+            return new URI("jrt", p, null);
         } catch (URISyntaxException ex) {
             throw new AssertionError(ex);
         }
--- a/test/jdk/jdk/internal/jrtfs/Basic.java	Tue May 28 14:53:57 2019 +0200
+++ b/test/jdk/jdk/internal/jrtfs/Basic.java	Tue May 28 19:30:30 2019 +0530
@@ -28,6 +28,7 @@
  */
 
 import java.io.InputStream;
+import java.io.IOError;
 import java.io.IOException;
 import java.io.DataInputStream;
 import java.nio.file.DirectoryStream;
@@ -271,17 +272,60 @@
         Path top = fs.getPath("/");
         try (Stream<Path> stream = Files.walk(top)) {
             stream.forEach(path -> {
-                URI u = path.toUri();
+                String pathStr = path.toAbsolutePath().toString();
+                URI u = null;
+                try {
+                    u = path.toUri();
+                } catch (IOError e) {
+                    assertFalse(pathStr.startsWith("/modules"));
+                    return;
+                }
+
                 assertTrue(u.getScheme().equalsIgnoreCase("jrt"));
                 assertFalse(u.isOpaque());
                 assertTrue(u.getAuthority() == null);
-                assertEquals(u.getPath(), path.toAbsolutePath().toString());
+
+                pathStr = pathStr.substring("/modules".length());
+                if (pathStr.isEmpty()) {
+                    pathStr = "/";
+                }
+                assertEquals(u.getPath(), pathStr);
                 Path p = Paths.get(u);
                 assertEquals(p, path);
             });
         }
     }
 
+    // @bug 8216553: JrtFIleSystemProvider getPath(URI) omits /modules element from file path
+    @Test
+    public void testPathToURIConversion() throws Exception {
+        var uri = URI.create("jrt:/java.base/module-info.class");
+        var path = Path.of(uri);
+        assertTrue(Files.exists(path));
+
+        uri = URI.create("jrt:/java.base/../java.base/module-info.class");
+        boolean seenIAE = false;
+        try {
+            Path.of(uri);
+        } catch (IllegalArgumentException iaExp) {
+            seenIAE = true;
+        }
+        assertTrue(seenIAE);
+
+        // check round-trip
+        var jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
+        assertTrue(Files.exists(jrtfs.getPath(path.toString())));
+
+        path = jrtfs.getPath("/modules/../modules/java.base/");
+        boolean seenIOError = false;
+        try {
+            path.toUri();
+        } catch (IOError ioError) {
+            seenIOError = true;
+        }
+        assertTrue(seenIOError);
+    }
+
     @Test
     public void testDirectoryNames() throws Exception {
         FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
--- a/test/langtools/tools/lib/toolbox/JarTask.java	Tue May 28 14:53:57 2019 +0200
+++ b/test/langtools/tools/lib/toolbox/JarTask.java	Tue May 28 19:30:30 2019 +0530
@@ -377,9 +377,9 @@
     private final Pattern jarEntry = Pattern.compile(".*!/(?:META-INF/sym/[^/]+/)?(.*)");
 
     /*
-     * A jrt: URL is of the form  jrt:/modules/<module>/<package>/<file>
+     * A jrt: URL is of the form  jrt:/<module>/<package>/<file>
      */
-    private final Pattern jrtEntry = Pattern.compile("/modules/([^/]+)/(.*)");
+    private final Pattern jrtEntry = Pattern.compile("/([^/]+)/(.*)");
 
     /*
      * A file: URL is of the form  file:/path/to/{modules,patches}/<module>/<package>/<file>