8067951: System.loadLibrary cannot find library when path contains quoted entry
Reviewed-by: sherman, rriggs, alanb
--- a/jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 09:05:50 2015 +0100
+++ b/jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 19:12:11 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,11 @@
private ClassLoaderHelper() {}
/**
+ * Indicates, whether PATH env variable is allowed to contain quoted entries.
+ */
+ static final boolean allowsQuotedPathElements = false;
+
+ /**
* Returns an alternate path name for the given file
* such that if the original pathname did not exist, then the
* file may be located at the alternate location.
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Mon Jan 19 09:05:50 2015 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Mon Jan 19 19:12:11 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1747,35 +1747,54 @@
private static String usr_paths[];
private static String sys_paths[];
- private static String[] initializePath(String propname) {
- String ldpath = System.getProperty(propname, "");
- String ps = File.pathSeparator;
- int ldlen = ldpath.length();
- int i, j, n;
- // Count the separators in the path
- i = ldpath.indexOf(ps);
- n = 0;
- while (i >= 0) {
- n++;
- i = ldpath.indexOf(ps, i + 1);
+ private static String[] initializePath(String propName) {
+ String ldPath = System.getProperty(propName, "");
+ int ldLen = ldPath.length();
+ char ps = File.pathSeparatorChar;
+ int psCount = 0;
+
+ if (ClassLoaderHelper.allowsQuotedPathElements &&
+ ldPath.indexOf('\"') >= 0) {
+ // First, remove quotes put around quoted parts of paths.
+ // Second, use a quotation mark as a new path separator.
+ // This will preserve any quoted old path separators.
+ char[] buf = new char[ldLen];
+ int bufLen = 0;
+ for (int i = 0; i < ldLen; ++i) {
+ char ch = ldPath.charAt(i);
+ if (ch == '\"') {
+ while (++i < ldLen &&
+ (ch = ldPath.charAt(i)) != '\"') {
+ buf[bufLen++] = ch;
+ }
+ } else {
+ if (ch == ps) {
+ psCount++;
+ ch = '\"';
+ }
+ buf[bufLen++] = ch;
+ }
+ }
+ ldPath = new String(buf, 0, bufLen);
+ ldLen = bufLen;
+ ps = '\"';
+ } else {
+ for (int i = ldPath.indexOf(ps); i >= 0;
+ i = ldPath.indexOf(ps, i + 1)) {
+ psCount++;
+ }
}
- // allocate the array of paths - n :'s = n + 1 path elements
- String[] paths = new String[n + 1];
-
- // Fill the array with paths from the ldpath
- n = i = 0;
- j = ldpath.indexOf(ps);
- while (j >= 0) {
- if (j - i > 0) {
- paths[n++] = ldpath.substring(i, j);
- } else if (j - i == 0) {
- paths[n++] = ".";
- }
- i = j + 1;
- j = ldpath.indexOf(ps, i);
+ String[] paths = new String[psCount + 1];
+ int pathStart = 0;
+ for (int j = 0; j < psCount; ++j) {
+ int pathEnd = ldPath.indexOf(ps, pathStart);
+ paths[j] = (pathStart < pathEnd) ?
+ ldPath.substring(pathStart, pathEnd) : ".";
+ pathStart = pathEnd + 1;
}
- paths[n] = ldpath.substring(i, ldlen);
+ paths[psCount] = (pathStart < ldLen) ?
+ ldPath.substring(pathStart, ldLen) : ".";
return paths;
}
--- a/jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 09:05:50 2015 +0100
+++ b/jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 19:12:11 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,11 @@
private ClassLoaderHelper() {}
/**
+ * Indicates, whether PATH env variable is allowed to contain quoted entries.
+ */
+ static final boolean allowsQuotedPathElements = false;
+
+ /**
* Returns an alternate path name for the given file
* such that if the original pathname did not exist, then the
* file may be located at the alternate location.
--- a/jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 09:05:50 2015 +0100
+++ b/jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 19:12:11 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,11 @@
private ClassLoaderHelper() {}
/**
+ * Indicates, whether PATH env variable is allowed to contain quoted entries.
+ */
+ static final boolean allowsQuotedPathElements = true;
+
+ /**
* Returns an alternate path name for the given file
* such that if the original pathname did not exist, then the
* file may be located at the alternate location.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java Mon Jan 19 19:12:11 2015 +0300
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8067951
+ * @summary Unit test for internal ClassLoader#initializePath().
+ * Quoted entries should get unquoted on Windows.
+ * Empty entries should be replaced with dot.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Platform
+ * @run main LibraryPathProperty
+ */
+
+import java.lang.reflect.Method;
+import java.io.File;
+import java.util.Arrays;
+import jdk.testlibrary.Platform;
+
+public class LibraryPathProperty {
+
+ static final String propName = "test.property.name";
+ static final String SP = File.pathSeparator;
+ static Method method;
+
+ public static void main(String[] args) throws Throwable {
+ method = ClassLoader.class
+ .getDeclaredMethod("initializePath",
+ String.class);
+ method.setAccessible(true);
+
+ test("", ".");
+ test(SP, ".", ".");
+ test("a" + SP, "a", ".");
+ test(SP + "b", ".", "b");
+ test("a" + SP + SP + "b", "a", ".", "b");
+
+ if (Platform.isWindows()) {
+ // on Windows parts of paths may be quoted
+ test("\"\"", ".");
+ test("\"\"" + SP, ".", ".");
+ test(SP + "\"\"", ".", ".");
+ test("a" + SP + "\"b\"" + SP, "a", "b", ".");
+ test(SP + "\"a\"" + SP + SP + "b", ".", "a", ".", "b");
+ test("\"a\"" + SP + "\"b\"", "a", "b");
+ test("\"/a/\"b" + SP + "c", "/a/b", "c");
+ test("\"/a;b\"" + SP + "c", "/a;b", "c");
+ test("\"/a:b\"" + SP + "c", "/a:b", "c");
+ test("\"/a" + SP + "b\"" + SP + "c", "/a" + SP + "b", "c");
+ test("/\"a\"\";\"\"b\"" + SP + "\"c\"", "/a;b", "c");
+ test("/\"a:\"b" + SP + "c", "/a:b", "c");
+ }
+ }
+
+ static void test(String s, String... expected) throws Throwable {
+ System.setProperty(propName, s);
+ String[] res = (String[])method.invoke(null, propName);
+ if (!Arrays.asList(res).equals(Arrays.asList(expected))) {
+ throw new RuntimeException("Parsing [" + s + "] " +
+ " result " + Arrays.asList(res) +
+ " doesn't match " + Arrays.asList(expected));
+ }
+ }
+}