summary refs log tree commit diff
path: root/library/std/src/os/windows/process.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-09 17:19:15 +0000
committerbors <bors@rust-lang.org>2024-04-09 17:19:15 +0000
commit25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04 (patch)
treeb4cc32646e9144cad1fbec590ff6c88e6fa7846e /library/std/src/os/windows/process.rs
parent7cf61ebde7b22796c69757901dd346d0fe70bd97 (diff)
parente7b09f5bf6a8d71c391713cd55935a9468009d52 (diff)
downloadrust-1.77.2.tar.gz
rust-1.77.2.zip
Auto merge of #123681 - pietroalbini:pa-cve-2024-24576-stable, r=pietroalbini 1.77.2
[stable] Prepare Rust 1.77.2

See https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html
Diffstat (limited to 'library/std/src/os/windows/process.rs')
-rw-r--r--library/std/src/os/windows/process.rs56
1 files changed, 54 insertions, 2 deletions
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 5bf0154eae3..19a593c4ab9 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -196,8 +196,60 @@ pub trait CommandExt: Sealed {
 
     /// Append literal text to the command line without any quoting or escaping.
     ///
-    /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
-    /// `CommandLineToArgvW` escaping rules.
+    /// This is useful for passing arguments to applications which doesn't follow
+    /// the standard C run-time escaping rules, such as `cmd.exe /c`.
+    ///
+    /// # Bat files
+    ///
+    /// Note the `cmd /c` command line has slightly different escaping rules then bat files
+    /// themselves. If possible, it may be better to write complex arguments to a temporary
+    /// .bat file, with appropriate escaping, and simply run that using:
+    ///
+    /// ```no_run
+    /// # use std::process::Command;
+    /// # let temp_bat_file = "";
+    /// # #[allow(unused)]
+    /// let output = Command::new("cmd").args(["/c", &format!("\"{temp_bat_file}\"")]).output();
+    /// ```
+    ///
+    /// # Example
+    ///
+    /// Run a bat script using both trusted and untrusted arguments.
+    ///
+    /// ```no_run
+    /// #[cfg(windows)]
+    /// // `my_script_path` is a path to known bat file.
+    /// // `user_name` is an untrusted name given by the user.
+    /// fn run_script(
+    ///     my_script_path: &str,
+    ///     user_name: &str,
+    /// ) -> Result<std::process::Output, std::io::Error> {
+    ///     use std::io::{Error, ErrorKind};
+    ///     use std::os::windows::process::CommandExt;
+    ///     use std::process::Command;
+    ///
+    ///     // Create the command line, making sure to quote the script path.
+    ///     // This assumes the fixed arguments have been tested to work with the script we're using.
+    ///     let mut cmd_args = format!(r#""{my_script_path}" "--features=[a,b,c]""#);
+    ///
+    ///     // Make sure the user name is safe. In particular we need to be
+    ///     // cautious of ascii symbols that cmd may interpret specially.
+    ///     // Here we only allow alphanumeric characters.
+    ///     if !user_name.chars().all(|c| c.is_alphanumeric()) {
+    ///         return Err(Error::new(ErrorKind::InvalidInput, "invalid user name"));
+    ///     }
+    ///     // now we've checked the user name, let's add that too.
+    ///     cmd_args.push(' ');
+    ///     cmd_args.push_str(&format!("--user {user_name}"));
+    ///
+    ///     // call cmd.exe and return the output
+    ///     Command::new("cmd.exe")
+    ///         .arg("/c")
+    ///         // surround the entire command in an extra pair of quotes, as required by cmd.exe.
+    ///         .raw_arg(&format!("\"{cmd_args}\""))
+    ///         .output()
+    /// }
+    /// ````
     #[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")]
     fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;