From 7afcf51fe4f635ff4e864ee13085397b41880fa6 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 4 Jun 2017 21:47:24 +0100 Subject: [PATCH] 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. --- src/libstd/sys/windows/process.rs | 18 ++++++++++-------- 1 file 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> { // Encode the command and arguments in a command line string such // that the spawned process may recover them using CommandLineToArgvW. let mut cmd: Vec = 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, arg: &OsStr) -> io::Result<()> { + fn append_arg(cmd: &mut Vec, 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 @@ fn test_wrapper(prog: &str, args: &[&str]) -> String { assert_eq!( test_wrapper("prog", &["aaa", "bbb", "ccc"]), - "prog aaa bbb ccc" + "\"prog\" aaa bbb ccc" ); assert_eq!( @@ -539,15 +541,15 @@ fn test_wrapper(prog: &str, args: &[&str]) -> String { ); 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}\"" ); } }