提交 6fcd2fed 编写于 作者: M michaelm

7034570: java.lang.Runtime.exec(String[] cmd, String[] env) can not work...

7034570: java.lang.Runtime.exec(String[] cmd, String[] env) can not work properly if SystemRoot not inherited
Reviewed-by: dholmes, alanb
上级 46c1309d
...@@ -938,6 +938,11 @@ public final class ProcessBuilder ...@@ -938,6 +938,11 @@ public final class ProcessBuilder
* but at the very least the command must be a non-empty list of * but at the very least the command must be a non-empty list of
* non-null strings. * non-null strings.
* *
* <p>A minimal set of system dependent environment variables may
* be required to start a process on some operating systems.
* As a result, the subprocess may inherit additional environment variable
* settings beyond those in the process builder's {@link #environment()}.
*
* <p>If there is a security manager, its * <p>If there is a security manager, its
* {@link SecurityManager#checkExec checkExec} * {@link SecurityManager#checkExec checkExec}
* method is called with the first component of this object's * method is called with the first component of this object's
......
...@@ -544,6 +544,11 @@ public class Runtime { ...@@ -544,6 +544,11 @@ public class Runtime {
* <p>If <tt>envp</tt> is <tt>null</tt>, the subprocess inherits the * <p>If <tt>envp</tt> is <tt>null</tt>, the subprocess inherits the
* environment settings of the current process. * environment settings of the current process.
* *
* <p>A minimal set of system dependent environment variables may
* be required to start a process on some operating systems.
* As a result, the subprocess may inherit additional environment variable
* settings beyond those in the specified environment.
*
* <p>{@link ProcessBuilder#start()} is now the preferred way to * <p>{@link ProcessBuilder#start()} is now the preferred way to
* start a process with a modified environment. * start a process with a modified environment.
* *
......
...@@ -143,7 +143,7 @@ final class ProcessEnvironment extends HashMap<String,String> ...@@ -143,7 +143,7 @@ final class ProcessEnvironment extends HashMap<String,String>
public void remove() { i.remove();} public void remove() { i.remove();}
}; };
} }
private static Map.Entry<String,String> checkedEntry (Object o) { private static Map.Entry<String,String> checkedEntry(Object o) {
Map.Entry<String,String> e = (Map.Entry<String,String>) o; Map.Entry<String,String> e = (Map.Entry<String,String>) o;
nonNullString(e.getKey()); nonNullString(e.getKey());
nonNullString(e.getValue()); nonNullString(e.getValue());
...@@ -285,7 +285,7 @@ final class ProcessEnvironment extends HashMap<String,String> ...@@ -285,7 +285,7 @@ final class ProcessEnvironment extends HashMap<String,String>
return (Map<String,String>) theEnvironment.clone(); return (Map<String,String>) theEnvironment.clone();
} }
// Only for use by Runtime.exec(...String[]envp...) // Only for use by ProcessBuilder.environment(String[] envp)
static Map<String,String> emptyEnvironment(int capacity) { static Map<String,String> emptyEnvironment(int capacity) {
return new ProcessEnvironment(capacity); return new ProcessEnvironment(capacity);
} }
...@@ -299,19 +299,46 @@ final class ProcessEnvironment extends HashMap<String,String> ...@@ -299,19 +299,46 @@ final class ProcessEnvironment extends HashMap<String,String>
Collections.sort(list, entryComparator); Collections.sort(list, entryComparator);
StringBuilder sb = new StringBuilder(size()*30); StringBuilder sb = new StringBuilder(size()*30);
for (Map.Entry<String,String> e : list) int cmp = -1;
sb.append(e.getKey())
.append('=') // Some versions of MSVCRT.DLL require SystemRoot to be set.
.append(e.getValue()) // So, we make sure that it is always set, even if not provided
.append('\u0000'); // by the caller.
// Ensure double NUL termination, final String SYSTEMROOT = "SystemRoot";
// even if environment is empty.
if (sb.length() == 0) for (Map.Entry<String,String> e : list) {
String key = e.getKey();
String value = e.getValue();
if (cmp < 0 && (cmp = nameComparator.compare(key, SYSTEMROOT)) > 0) {
// Not set, so add it here
addToEnvIfSet(sb, SYSTEMROOT);
}
addToEnv(sb, key, value);
}
if (cmp < 0) {
// Got to end of list and still not found
addToEnvIfSet(sb, SYSTEMROOT);
}
if (sb.length() == 0) {
// Environment was empty and SystemRoot not set in parent
sb.append('\u0000'); sb.append('\u0000');
}
// Block is double NUL terminated
sb.append('\u0000'); sb.append('\u0000');
return sb.toString(); return sb.toString();
} }
// add the environment variable to the child, if it exists in parent
private static void addToEnvIfSet(StringBuilder sb, String name) {
String s = getenv(name);
if (s != null)
addToEnv(sb, name, s);
}
private static void addToEnv(StringBuilder sb, String name, String val) {
sb.append(name).append('=').append(val).append('\u0000');
}
static String toEnvironmentBlock(Map<String,String> map) { static String toEnvironmentBlock(Map<String,String> map) {
return map == null ? null : return map == null ? null :
((ProcessEnvironment)map).toEnvironmentBlock(); ((ProcessEnvironment)map).toEnvironmentBlock();
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689 * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
* 4947220 7018606 * 4947220 7018606 7034570
* @summary Basic tests for Process and Environment Variable code * @summary Basic tests for Process and Environment Variable code
* @run main/othervm/timeout=300 Basic * @run main/othervm/timeout=300 Basic
* @author Martin Buchholz * @author Martin Buchholz
...@@ -1440,11 +1440,12 @@ public class Basic { ...@@ -1440,11 +1440,12 @@ public class Basic {
// Check for sort order of environment variables on Windows. // Check for sort order of environment variables on Windows.
//---------------------------------------------------------------- //----------------------------------------------------------------
try { try {
String systemRoot = "SystemRoot=" + System.getenv("SystemRoot");
// '+' < 'A' < 'Z' < '_' < 'a' < 'z' < '~' // '+' < 'A' < 'Z' < '_' < 'a' < 'z' < '~'
String[]envp = {"FOO=BAR","BAZ=GORP","QUUX=", String[]envp = {"FOO=BAR","BAZ=GORP","QUUX=",
"+=+", "_=_", "~=~"}; "+=+", "_=_", "~=~", systemRoot};
String output = nativeEnv(envp); String output = nativeEnv(envp);
String expected = "+=+\nBAZ=GORP\nFOO=BAR\nQUUX=\n_=_\n~=~\n"; String expected = "+=+\nBAZ=GORP\nFOO=BAR\nQUUX=\n"+systemRoot+"\n_=_\n~=~\n";
// On Windows, Java must keep the environment sorted. // On Windows, Java must keep the environment sorted.
// Order is random on Unix, so this test does the sort. // Order is random on Unix, so this test does the sort.
if (! Windows.is()) if (! Windows.is())
...@@ -1452,6 +1453,21 @@ public class Basic { ...@@ -1452,6 +1453,21 @@ public class Basic {
equal(output, expected); equal(output, expected);
} catch (Throwable t) { unexpected(t); } } catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// Test Runtime.exec(...envp...)
// and check SystemRoot gets set automatically on Windows
//----------------------------------------------------------------
try {
if (Windows.is()) {
String systemRoot = "SystemRoot=" + System.getenv("SystemRoot");
String[]envp = {"FOO=BAR","BAZ=GORP","QUUX=",
"+=+", "_=_", "~=~"};
String output = nativeEnv(envp);
String expected = "+=+\nBAZ=GORP\nFOO=BAR\nQUUX=\n"+systemRoot+"\n_=_\n~=~\n";
equal(output, expected);
}
} catch (Throwable t) { unexpected(t); }
//---------------------------------------------------------------- //----------------------------------------------------------------
// System.getenv() must be consistent with System.getenv(String) // System.getenv() must be consistent with System.getenv(String)
//---------------------------------------------------------------- //----------------------------------------------------------------
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册