fix(runtime): allow nul device on windows (#23741)

Fixes [23721](https://github.com/denoland/deno/issues/23721)
This commit is contained in:
Matt Mastracci 2024-05-08 14:39:06 -06:00 committed by GitHub
parent 547ce6c3b8
commit 9f7f681e26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 4 deletions

View file

@ -890,7 +890,15 @@ fn open_with_access_check(
access_check: Option<AccessCheckCb>, access_check: Option<AccessCheckCb>,
) -> FsResult<std::fs::File> { ) -> FsResult<std::fs::File> {
if let Some(access_check) = access_check { if let Some(access_check) = access_check {
let path = if path.is_absolute() { let path_bytes = path.as_os_str().as_encoded_bytes();
let is_windows_device_path = cfg!(windows)
&& path_bytes.starts_with(br"\\.\")
&& !path_bytes.contains(&b':');
let path = if is_windows_device_path {
// On Windows, normalize_path doesn't work with device-prefix-style
// paths. We pass these through.
path.to_owned()
} else if path.is_absolute() {
normalize_path(path) normalize_path(path)
} else { } else {
let cwd = current_dir()?; let cwd = current_dir()?;
@ -898,8 +906,8 @@ fn open_with_access_check(
}; };
(*access_check)(false, &path, &options)?; (*access_check)(false, &path, &options)?;
// On Linux, /proc may contain magic links that we don't want to resolve // On Linux, /proc may contain magic links that we don't want to resolve
let needs_canonicalization = let needs_canonicalization = !is_windows_device_path
!cfg!(target_os = "linux") || path.starts_with("/proc"); && (!cfg!(target_os = "linux") || path.starts_with("/proc"));
let path = if needs_canonicalization { let path = if needs_canonicalization {
match path.canonicalize() { match path.canonicalize() {
Ok(path) => path, Ok(path) => path,
@ -916,7 +924,6 @@ fn open_with_access_check(
} else { } else {
path path
}; };
(*access_check)(true, &path, &options)?; (*access_check)(true, &path, &options)?;
// For windows // For windows

View file

@ -1696,6 +1696,12 @@ impl PermissionsContainer {
self.check_was_allow_all_flag_passed().map_err(error_all)?; self.check_was_allow_all_flag_passed().map_err(error_all)?;
} }
} else if cfg!(target_os = "windows") { } else if cfg!(target_os = "windows") {
// \\.\nul is allowed
let s = path.as_os_str().as_encoded_bytes();
if s.eq_ignore_ascii_case(br#"\\.\nul"#) {
return Ok(());
}
fn is_normalized_windows_drive_path(path: &Path) -> bool { fn is_normalized_windows_drive_path(path: &Path) -> bool {
let s = path.as_os_str().as_encoded_bytes(); let s = path.as_os_str().as_encoded_bytes();
// \\?\X:\ // \\?\X:\

View file

@ -5,6 +5,7 @@ const testCases = [
// Allowed, safe // Allowed, safe
[["darwin", "linux"], null, "/dev/null"], [["darwin", "linux"], null, "/dev/null"],
[["darwin", "linux"], null, "/etc/passwd"], [["darwin", "linux"], null, "/etc/passwd"],
[["windows"], null, "\\\\.\\nul"],
// Denied, requires `--allow-all` // Denied, requires `--allow-all`
[["darwin", "linux"], /PermissionDenied/, "/dev/ptmx"], [["darwin", "linux"], /PermissionDenied/, "/dev/ptmx"],
[["linux"], /PermissionDenied/, "/proc/self/environ"], [["linux"], /PermissionDenied/, "/proc/self/environ"],
@ -40,6 +41,7 @@ for (const [oses, error, file] of testCases) {
console.log(`Got an error (expected) for ${file}: ${e}`); console.log(`Got an error (expected) for ${file}: ${e}`);
} else { } else {
console.log(`*** Got an unexpected error for ${file}: ${e}`); console.log(`*** Got an unexpected error for ${file}: ${e}`);
failed = true;
} }
} }
} }