8174797: jshell tool: invalid module path crashes tool
authorrfield
Mon, 13 Feb 2017 08:50:26 -0800
changeset 43856 fcdebb803c62
parent 43773 8d8593871575
child 43857 37614a3b7193
8174797: jshell tool: invalid module path crashes tool 8174796: jshell tool: regression: user home (tilde) not translated Reviewed-by: jlahoda
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java
langtools/test/jdk/jshell/ToolBasicTest.java
langtools/test/jdk/jshell/ToolSimpleTest.java
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Mon Feb 13 11:57:56 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Mon Feb 13 08:50:26 2017 -0800
@@ -349,9 +349,56 @@
             }
         }
 
+        // check that the supplied string represent valid class/module paths
+        // converting any ~/ to user home
+        private Collection<String> validPaths(Collection<String> vals, String context, boolean isModulePath) {
+            Stream<String> result = vals.stream()
+                    .map(s -> Arrays.stream(s.split(File.pathSeparator))
+                        .map(sp -> toPathResolvingUserHome(sp))
+                        .filter(p -> checkValidPathEntry(p, context, isModulePath))
+                        .map(p -> p.toString())
+                        .collect(Collectors.joining(File.pathSeparator)));
+            if (failed) {
+                return Collections.emptyList();
+            } else {
+                return result.collect(toList());
+            }
+        }
+
+        // Adapted from compiler method Locations.checkValidModulePathEntry
+        private boolean checkValidPathEntry(Path p, String context, boolean isModulePath) {
+            if (!Files.exists(p)) {
+                msg("jshell.err.file.not.found", context, p);
+                failed = true;
+                return false;
+            }
+            if (Files.isDirectory(p)) {
+                // if module-path, either an exploded module or a directory of modules
+                return true;
+            }
+
+            String name = p.getFileName().toString();
+            int lastDot = name.lastIndexOf(".");
+            if (lastDot > 0) {
+                switch (name.substring(lastDot)) {
+                    case ".jar":
+                        return true;
+                    case ".jmod":
+                        if (isModulePath) {
+                            return true;
+                        }
+                }
+            }
+            msg("jshell.err.arg", context, p);
+            failed = true;
+            return false;
+        }
+
         Options parse(OptionSet options) {
-            addOptions(OptionKind.CLASS_PATH, options.valuesOf(argClassPath));
-            addOptions(OptionKind.MODULE_PATH, options.valuesOf(argModulePath));
+            addOptions(OptionKind.CLASS_PATH,
+                    validPaths(options.valuesOf(argClassPath), "--class-path", false));
+            addOptions(OptionKind.MODULE_PATH,
+                    validPaths(options.valuesOf(argModulePath), "--module-path", true));
             addOptions(OptionKind.ADD_MODULES, options.valuesOf(argAddModules));
             addOptions(OptionKind.ADD_EXPORTS, options.valuesOf(argAddExports).stream()
                     .map(mp -> mp.contains("=") ? mp : mp + "=ALL-UNNAMED")
--- a/langtools/test/jdk/jshell/ToolBasicTest.java	Mon Feb 13 11:57:56 2017 +0100
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java	Mon Feb 13 08:50:26 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102 8165405
+ * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102 8165405 8174796 8174797
  * @summary Tests for Basic tests for REPL tool
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -35,6 +35,7 @@
  * @run testng/timeout=600 ToolBasicTest
  */
 
+import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -272,23 +273,58 @@
         );
     }
 
-    public void testClasspathJar() {
+    private String makeSimpleJar() {
         Compiler compiler = new Compiler();
         Path outDir = Paths.get("testClasspathJar");
         compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
         String jarName = "test.jar";
         compiler.jar(outDir, jarName, "pkg/A.class");
-        Path jarPath = compiler.getPath(outDir).resolve(jarName);
+        return compiler.getPath(outDir).resolve(jarName).toString();
+    }
+
+    public void testClasspathJar() {
+        String jarPath = makeSimpleJar();
         test(
                 (a) -> assertCommand(a, "/env --class-path " + jarPath,
                         "|  Setting new options and restoring state."),
                 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
         );
-        test(new String[] { "--class-path", jarPath.toString() },
+        test(new String[] { "--class-path", jarPath },
                 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
         );
     }
 
+    public void testClasspathUserHomeExpansion() {
+        String jarPath = makeSimpleJar();
+        String tilde = "~" + File.separator;
+        test(
+                (a) -> assertCommand(a, "/env --class-path " + tilde + "forblato",
+                        "|  File '" + System.getProperty("user.home") + File.separator
+                                + "forblato' for '--class-path' is not found."),
+                (a) -> assertCommand(a, "/env --class-path " + jarPath + File.pathSeparator
+                                                            + tilde + "forblato",
+                        "|  File '" + System.getProperty("user.home") + File.separator
+                                + "forblato' for '--class-path' is not found.")
+        );
+    }
+
+    public void testBadClasspath() {
+        String jarPath = makeSimpleJar();
+        Compiler compiler = new Compiler();
+        Path t1 = compiler.getPath("whatever/thing.zip");
+        compiler.writeToFile(t1, "");
+        Path t2 = compiler.getPath("whatever/thing.jmod");
+        compiler.writeToFile(t2, "");
+        test(
+                (a) -> assertCommand(a, "/env --class-path " + t1.toString(),
+                        "|  Invalid '--class-path' argument: " + t1.toString()),
+                (a) -> assertCommand(a, "/env --class-path " + jarPath + File.pathSeparator + t1.toString(),
+                        "|  Invalid '--class-path' argument: " + t1.toString()),
+                (a) -> assertCommand(a, "/env --class-path " + t2.toString(),
+                        "|  Invalid '--class-path' argument: " + t2.toString())
+        );
+    }
+
     public void testModulePath() {
         Compiler compiler = new Compiler();
         Path modsDir = Paths.get("mods");
@@ -304,6 +340,25 @@
         );
     }
 
+    public void testModulePathUserHomeExpansion() {
+        String tilde = "~" + File.separatorChar;
+        test(
+                (a) -> assertCommand(a, "/env --module-path " + tilde + "snardugol",
+                        "|  File '" + System.getProperty("user.home")
+                                + File.separatorChar + "snardugol' for '--module-path' is not found.")
+        );
+    }
+
+    public void testBadModulePath() {
+        Compiler compiler = new Compiler();
+        Path t1 = compiler.getPath("whatever/thing.zip");
+        compiler.writeToFile(t1, "");
+        test(
+                (a) -> assertCommand(a, "/env --module-path " + t1.toString(),
+                        "|  Invalid '--module-path' argument: " + t1.toString())
+        );
+    }
+
     public void testStartupFileOption() {
         Compiler compiler = new Compiler();
         Path startup = compiler.getPath("StartupFileOption/startup.txt");
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java	Mon Feb 13 11:57:56 2017 +0100
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java	Mon Feb 13 08:50:26 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103  8165405 8173073 8173848 8174041 8173916 8174028 8174262
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103  8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -212,6 +212,14 @@
     }
 
     @Test
+    public void testInvalidClassPath() {
+        test(
+                a -> assertCommand(a, "/env --class-path snurge/fusal",
+                        "|  File 'snurge/fusal' for '--class-path' is not found.")
+        );
+    }
+
+    @Test
     public void testNoArgument() {
         test(
                 (a) -> assertCommand(a, "/save",