Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions library/std/src/process/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,22 @@ fn env_empty() {
let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
assert!(p.is_ok());
}

// See issue #91991
#[test]
#[cfg(windows)]
fn run_bat_script() {
let tempdir = crate::sys_common::io::test::tmpdir();
let script_path = tempdir.join("hello.cmd");

crate::fs::write(&script_path, "@echo Hello, %~1!").unwrap();
let output = Command::new(&script_path)
.arg("fellow Rustaceans")
.stdout(crate::process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!");
}
16 changes: 16 additions & 0 deletions library/std/src/sys/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,19 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
// 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();

// CreateFileW has special handling for .bat and .cmd files, which means we
// need to add an extra pair of quotes surrounding the whole command line
// so they are properly passed on to the script.
// See issue #91991.
let is_batch_file = Path::new(prog)
.extension()
.map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat"))
.unwrap_or(false);
if is_batch_file {
cmd.push(b'"' as u16);
}

// 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, Quote::Always)?;
Expand All @@ -715,6 +728,9 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
};
append_arg(&mut cmd, arg, quote)?;
}
if is_batch_file {
cmd.push(b'"' as u16);
}
return Ok(cmd);

fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {
Expand Down