about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorOliver Middleton <olliemail27@gmail.com>2017-06-04 21:47:24 +0100
committerOliver Middleton <olliemail27@gmail.com>2017-06-04 21:47:24 +0100
commit7afcf51fe4f635ff4e864ee13085397b41880fa6 (patch)
treef8498827dc96cd05f6c448a23d404469f64f0a04 /src/libstd/sys
parent0da9721ab49d80bf74208e94a891b12c4a248507 (diff)
downloadrust-7afcf51fe4f635ff4e864ee13085397b41880fa6.tar.gz
rust-7afcf51fe4f635ff4e864ee13085397b41880fa6.zip
Always quote program name in Command::spawn on Windows
`CreateProcess` will interpret args as part of the binary name if it
doesn't find the binary using just the unquoted name. For example if
`foo.exe` doesn't exist, `Command::new("foo").arg("bar").spawn()` will
try to launch `foo bar.exe` which is clearly not desired.
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/windows/process.rs18
1 files changed, 10 insertions, 8 deletions
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index dfbc1b581ee..0bd0ce73138 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -427,20 +427,22 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
     // Encode the command and arguments in a command line string such
     // that the spawned process may recover them using CommandLineToArgvW.
     let mut cmd: Vec<u16> = Vec::new();
-    append_arg(&mut cmd, prog)?;
+    // Always quote the program name so CreateProcess doesn't interpret args as
+    // part of the name if the binary wasn't found first time.
+    append_arg(&mut cmd, prog, true)?;
     for arg in args {
         cmd.push(' ' as u16);
-        append_arg(&mut cmd, arg)?;
+        append_arg(&mut cmd, arg, false)?;
     }
     return Ok(cmd);
 
-    fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr) -> io::Result<()> {
+    fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, force_quotes: bool) -> io::Result<()> {
         // If an argument has 0 characters then we need to quote it to ensure
         // that it actually gets passed through on the command line or otherwise
         // it will be dropped entirely when parsed on the other end.
         ensure_no_nuls(arg)?;
         let arg_bytes = &arg.as_inner().inner.as_inner();
-        let quote = arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t')
+        let quote = force_quotes || arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t')
             || arg_bytes.is_empty();
         if quote {
             cmd.push('"' as u16);
@@ -526,7 +528,7 @@ mod tests {
 
         assert_eq!(
             test_wrapper("prog", &["aaa", "bbb", "ccc"]),
-            "prog aaa bbb ccc"
+            "\"prog\" aaa bbb ccc"
         );
 
         assert_eq!(
@@ -539,15 +541,15 @@ mod tests {
         );
         assert_eq!(
             test_wrapper("echo", &["a b c"]),
-            "echo \"a b c\""
+            "\"echo\" \"a b c\""
         );
         assert_eq!(
             test_wrapper("echo", &["\" \\\" \\", "\\"]),
-            "echo \"\\\" \\\\\\\" \\\\\" \\"
+            "\"echo\" \"\\\" \\\\\\\" \\\\\" \\"
         );
         assert_eq!(
             test_wrapper("\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}", &[]),
-            "\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}"
+            "\"\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}\""
         );
     }
 }