diff options
-rw-r--r-- | crates/cli/src/decompress.rs | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/crates/cli/src/decompress.rs b/crates/cli/src/decompress.rs index 0ef546b9..72eefdda 100644 --- a/crates/cli/src/decompress.rs +++ b/crates/cli/src/decompress.rs @@ -132,7 +132,7 @@ impl DecompressionMatcherBuilder { A: AsRef<OsStr>, { let glob = glob.to_string(); - let bin = resolve_binary(Path::new(program.as_ref()))?; + let bin = try_resolve_binary(Path::new(program.as_ref()))?; let args = args.into_iter().map(|a| a.as_ref().to_os_string()).collect(); self.commands.push(DecompressionCommand { glob, bin, args }); @@ -422,6 +422,34 @@ impl io::Read for DecompressionReader { pub fn resolve_binary<P: AsRef<Path>>( prog: P, ) -> Result<PathBuf, CommandError> { + if !cfg!(windows) { + return Ok(prog.as_ref().to_path_buf()); + } + try_resolve_binary(prog) +} + +/// Resolves a path to a program to a path by searching for the program in +/// `PATH`. +/// +/// If the program could not be resolved, then an error is returned. +/// +/// The purpose of doing this instead of passing the path to the program +/// directly to Command::new is that Command::new will hand relative paths +/// to CreateProcess on Windows, which will implicitly search the current +/// working directory for the executable. This could be undesirable for +/// security reasons. e.g., running ripgrep with the -z/--search-zip flag on an +/// untrusted directory tree could result in arbitrary programs executing on +/// Windows. +/// +/// Note that this could still return a relative path if PATH contains a +/// relative path. We permit this since it is assumed that the user has set +/// this explicitly, and thus, desires this behavior. +/// +/// If `check_exists` is false or the path is already an absolute path this +/// will return immediately. +fn try_resolve_binary<P: AsRef<Path>>( + prog: P, +) -> Result<PathBuf, CommandError> { use std::env; fn is_exe(path: &Path) -> bool { @@ -433,7 +461,7 @@ pub fn resolve_binary<P: AsRef<Path>>( } let prog = prog.as_ref(); - if !cfg!(windows) || prog.is_absolute() { + if prog.is_absolute() { return Ok(prog.to_path_buf()); } let syspaths = match env::var_os("PATH") { |