Skip to content

scolapasta-path incorrectly mutates verbatim paths on Windows #2567

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lopopolo opened this issue May 22, 2023 · 0 comments · Fixed by #2600
Closed

scolapasta-path incorrectly mutates verbatim paths on Windows #2567

lopopolo opened this issue May 22, 2023 · 0 comments · Fixed by #2600
Labels
A-filesystem Area: Filesystem access and implementations. C-bug Category: This is a bug. E-easy Call for participation: Experience needed to fix: Easy / not much. O-windows Target: Support for building on Windows targets like `x86_64-pc-windows-msvc`.

Comments

@lopopolo
Copy link
Member

pub fn normalize_slashes(path: PathBuf) -> Result<Vec<u8>, PathBuf> {
let mut buf = OsString::from(path).into_string()?.into_bytes();
for byte in &mut buf {
if *byte == b'\\' {
*byte = b'/';
}
}
Ok(buf)
}

This routine should check to see if the path is a "verbatim path" (also knowns as a Windows extended-length path), which means it has a prefix of \\?\. These paths should not be modified. The Ruby engine should treat them as opaque.

See: https://users.rust-lang.org/t/understanding-windows-paths/58583.

This can be checked by using the Path::components iterator and checking whether the first element yielded by this iterator is Component::Prefix where the inner prefix_component.kind().is_verbatim() gives true.

The Prefix docs give these examples for the various types of paths, which we should add tests for:

assert_eq!(Verbatim(OsStr::new("pictures")),
           get_path_prefix(r"\\?\pictures\kittens"));
assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),
           get_path_prefix(r"\\?\UNC\server\share"));
assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));
assert_eq!(DeviceNS(OsStr::new("BrainInterface")),
           get_path_prefix(r"\\.\BrainInterface"));
assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),
           get_path_prefix(r"\\server\share"));
assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));

The linked discourse thread also includes these examples:

\\?\UNC\server\share\folder\file.txt
\\?\C:\foo
@lopopolo lopopolo added C-bug Category: This is a bug. A-filesystem Area: Filesystem access and implementations. O-windows Target: Support for building on Windows targets like `x86_64-pc-windows-msvc`. E-easy Call for participation: Experience needed to fix: Easy / not much. labels May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-filesystem Area: Filesystem access and implementations. C-bug Category: This is a bug. E-easy Call for participation: Experience needed to fix: Easy / not much. O-windows Target: Support for building on Windows targets like `x86_64-pc-windows-msvc`.
Development

Successfully merging a pull request may close this issue.

1 participant