Skip to content

Commit 93f627d

Browse files
committed
Keep the path after program_exists succeeds
1 parent d4686c6 commit 93f627d

File tree

1 file changed

+23
-22
lines changed

1 file changed

+23
-22
lines changed

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

+23-22
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,11 @@ impl Command {
269269
None
270270
};
271271
let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?;
272-
let is_batch_file = program
273-
.extension()
274-
.map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat"))
275-
.unwrap_or(false);
276-
let program = path::maybe_verbatim(&program)?;
272+
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
273+
let is_batch_file = matches!(
274+
program.len().checked_sub(5).and_then(|i| program.get(i..)),
275+
Some([46, 98 | 66, 97 | 65, 116 | 84, 0] | [46, 99 | 67, 109 | 77, 100 | 68, 0])
276+
);
277277
let mut cmd_str =
278278
make_command_line(&program, &self.args, self.force_quotes_enabled, is_batch_file)?;
279279
cmd_str.push(0); // add null terminator
@@ -370,7 +370,7 @@ fn resolve_exe<'a>(
370370
exe_path: &'a OsStr,
371371
parent_paths: impl FnOnce() -> Option<OsString>,
372372
child_paths: Option<&OsStr>,
373-
) -> io::Result<PathBuf> {
373+
) -> io::Result<Vec<u16>> {
374374
// Early return if there is no filename.
375375
if exe_path.is_empty() || path::has_trailing_slash(exe_path) {
376376
return Err(io::const_io_error!(
@@ -392,19 +392,19 @@ fn resolve_exe<'a>(
392392
if has_exe_suffix {
393393
// The application name is a path to a `.exe` file.
394394
// Let `CreateProcessW` figure out if it exists or not.
395-
return Ok(exe_path.into());
395+
return path::maybe_verbatim(Path::new(exe_path));
396396
}
397397
let mut path = PathBuf::from(exe_path);
398398

399399
// Append `.exe` if not already there.
400400
path = path::append_suffix(path, EXE_SUFFIX.as_ref());
401-
if program_exists(&path) {
401+
if let Some(path) = program_exists(&path) {
402402
return Ok(path);
403403
} else {
404404
// It's ok to use `set_extension` here because the intent is to
405405
// remove the extension that was just added.
406406
path.set_extension("");
407-
return Ok(path);
407+
return path::maybe_verbatim(&path);
408408
}
409409
} else {
410410
ensure_no_nuls(exe_path)?;
@@ -419,7 +419,7 @@ fn resolve_exe<'a>(
419419
if !has_extension {
420420
path.set_extension(EXE_EXTENSION);
421421
}
422-
if program_exists(&path) { Some(path) } else { None }
422+
program_exists(&path)
423423
});
424424
if let Some(path) = result {
425425
return Ok(path);
@@ -435,10 +435,10 @@ fn search_paths<Paths, Exists>(
435435
parent_paths: Paths,
436436
child_paths: Option<&OsStr>,
437437
mut exists: Exists,
438-
) -> Option<PathBuf>
438+
) -> Option<Vec<u16>>
439439
where
440440
Paths: FnOnce() -> Option<OsString>,
441-
Exists: FnMut(PathBuf) -> Option<PathBuf>,
441+
Exists: FnMut(PathBuf) -> Option<Vec<u16>>,
442442
{
443443
// 1. Child paths
444444
// This is for consistency with Rust's historic behaviour.
@@ -490,17 +490,18 @@ where
490490
}
491491

492492
/// Check if a file exists without following symlinks.
493-
fn program_exists(path: &Path) -> bool {
493+
fn program_exists(path: &Path) -> Option<Vec<u16>> {
494494
unsafe {
495-
to_u16s(path)
496-
.map(|path| {
497-
// Getting attributes using `GetFileAttributesW` does not follow symlinks
498-
// and it will almost always be successful if the link exists.
499-
// There are some exceptions for special system files (e.g. the pagefile)
500-
// but these are not executable.
501-
c::GetFileAttributesW(path.as_ptr()) != c::INVALID_FILE_ATTRIBUTES
502-
})
503-
.unwrap_or(false)
495+
let path = path::maybe_verbatim(path).ok()?;
496+
// Getting attributes using `GetFileAttributesW` does not follow symlinks
497+
// and it will almost always be successful if the link exists.
498+
// There are some exceptions for special system files (e.g. the pagefile)
499+
// but these are not executable.
500+
if c::GetFileAttributesW(path.as_ptr()) == c::INVALID_FILE_ATTRIBUTES {
501+
None
502+
} else {
503+
Some(path)
504+
}
504505
}
505506
}
506507

0 commit comments

Comments
 (0)