Skip to content

Commit de764a7

Browse files
committed
Quote bat script command line
1 parent f840216 commit de764a7

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

library/std/src/process/tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,22 @@ fn env_empty() {
416416
let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
417417
assert!(p.is_ok());
418418
}
419+
420+
// See issue #91991
421+
#[test]
422+
#[cfg(windows)]
423+
fn run_bat_script() {
424+
let tempdir = crate::sys_common::io::test::tmpdir();
425+
let script_path = tempdir.join("hello.cmd");
426+
427+
crate::fs::write(&script_path, "@echo Hello, %~1!").unwrap();
428+
let output = Command::new(&script_path)
429+
.arg("fellow Rustaceans")
430+
.stdout(crate::process::Stdio::piped())
431+
.spawn()
432+
.unwrap()
433+
.wait_with_output()
434+
.unwrap();
435+
assert!(output.status.success());
436+
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!");
437+
}

library/std/src/sys/windows/process.rs

+16
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,19 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
704704
// Encode the command and arguments in a command line string such
705705
// that the spawned process may recover them using CommandLineToArgvW.
706706
let mut cmd: Vec<u16> = Vec::new();
707+
708+
// CreateFileW has special handling for .bat and .cmd files, which means we
709+
// need to add an extra pair of quotes surrounding the whole command line
710+
// so they are properly passed on to the script.
711+
// See issue #91991.
712+
let is_batch_file = Path::new(prog)
713+
.extension()
714+
.map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat"))
715+
.unwrap_or(false);
716+
if is_batch_file {
717+
cmd.push(b'"' as u16);
718+
}
719+
707720
// Always quote the program name so CreateProcess doesn't interpret args as
708721
// part of the name if the binary wasn't found first time.
709722
append_arg(&mut cmd, prog, Quote::Always)?;
@@ -715,6 +728,9 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
715728
};
716729
append_arg(&mut cmd, arg, quote)?;
717730
}
731+
if is_batch_file {
732+
cmd.push(b'"' as u16);
733+
}
718734
return Ok(cmd);
719735

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

0 commit comments

Comments
 (0)