Skip to content

Commit e31898b

Browse files
committed
Reduce unsafe scope
1 parent 0281a05 commit e31898b

File tree

1 file changed

+48
-49
lines changed

1 file changed

+48
-49
lines changed

src/libstd/sys/windows/path.rs

+48-49
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ mod tests;
88
pub const MAIN_SEP_STR: &str = "\\";
99
pub const MAIN_SEP: char = '\\';
1010

11+
// The unsafety here stems from converting between `&OsStr` and `&[u8]`
12+
// and back. This is safe to do because (1) we only look at ASCII
13+
// contents of the encoding and (2) new &OsStr values are produced
14+
// only from ASCII-bounded slices of existing &OsStr values.
1115
fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
1216
unsafe { mem::transmute(s) }
1317
}
@@ -33,62 +37,57 @@ pub fn is_valid_drive_letter(disk: u8) -> bool {
3337

3438
pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
3539
use Prefix::{DeviceNS, Disk, Verbatim, VerbatimDisk, VerbatimUNC, UNC};
36-
unsafe {
37-
// The unsafety here stems from converting between &OsStr and &[u8]
38-
// and back. This is safe to do because (1) we only look at ASCII
39-
// contents of the encoding and (2) new &OsStr values are produced
40-
// only from ASCII-bounded slices of existing &OsStr values.
41-
let path = os_str_as_u8_slice(path);
4240

43-
// \\
44-
if let Some(path) = path.strip_prefix(br"\\") {
45-
// \\?\
46-
if let Some(path) = path.strip_prefix(br"?\") {
47-
// \\?\UNC\server\share
48-
if let Some(path) = path.strip_prefix(br"UNC\") {
49-
let (server, share) = match get_first_two_components(path, is_verbatim_sep) {
50-
Some((server, share)) => {
51-
(u8_slice_as_os_str(server), u8_slice_as_os_str(share))
52-
}
53-
None => (u8_slice_as_os_str(path), OsStr::new("")),
54-
};
55-
return Some(VerbatimUNC(server, share));
56-
} else {
57-
// \\?\path
58-
match path {
59-
// \\?\C:\path
60-
[c, b':', b'\\', ..] if is_valid_drive_letter(*c) => {
61-
return Some(VerbatimDisk(c.to_ascii_uppercase()));
62-
}
63-
// \\?\cat_pics
64-
_ => {
65-
let idx = path.iter().position(|&b| b == b'\\').unwrap_or(path.len());
66-
let slice = &path[..idx];
67-
return Some(Verbatim(u8_slice_as_os_str(slice)));
68-
}
41+
let path = os_str_as_u8_slice(path);
42+
43+
// \\
44+
if let Some(path) = path.strip_prefix(br"\\") {
45+
// \\?\
46+
if let Some(path) = path.strip_prefix(br"?\") {
47+
// \\?\UNC\server\share
48+
if let Some(path) = path.strip_prefix(br"UNC\") {
49+
let (server, share) = match get_first_two_components(path, is_verbatim_sep) {
50+
Some((server, share)) => unsafe {
51+
(u8_slice_as_os_str(server), u8_slice_as_os_str(share))
52+
},
53+
None => (unsafe { u8_slice_as_os_str(path) }, OsStr::new("")),
54+
};
55+
return Some(VerbatimUNC(server, share));
56+
} else {
57+
// \\?\path
58+
match path {
59+
// \\?\C:\path
60+
[c, b':', b'\\', ..] if is_valid_drive_letter(*c) => {
61+
return Some(VerbatimDisk(c.to_ascii_uppercase()));
62+
}
63+
// \\?\cat_pics
64+
_ => {
65+
let idx = path.iter().position(|&b| b == b'\\').unwrap_or(path.len());
66+
let slice = &path[..idx];
67+
return Some(Verbatim(unsafe { u8_slice_as_os_str(slice) }));
6968
}
7069
}
71-
} else if let Some(path) = path.strip_prefix(b".\\") {
72-
// \\.\COM42
73-
let idx = path.iter().position(|&b| b == b'\\').unwrap_or(path.len());
74-
let slice = &path[..idx];
75-
return Some(DeviceNS(u8_slice_as_os_str(slice)));
76-
}
77-
match get_first_two_components(path, is_sep_byte) {
78-
Some((server, share)) if !server.is_empty() && !share.is_empty() => {
79-
// \\server\share
80-
return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
81-
}
82-
_ => {}
8370
}
84-
} else if let [c, b':', ..] = path {
85-
// C:
86-
if is_valid_drive_letter(*c) {
87-
return Some(Disk(c.to_ascii_uppercase()));
71+
} else if let Some(path) = path.strip_prefix(b".\\") {
72+
// \\.\COM42
73+
let idx = path.iter().position(|&b| b == b'\\').unwrap_or(path.len());
74+
let slice = &path[..idx];
75+
return Some(DeviceNS(unsafe { u8_slice_as_os_str(slice) }));
76+
}
77+
match get_first_two_components(path, is_sep_byte) {
78+
Some((server, share)) if !server.is_empty() && !share.is_empty() => {
79+
// \\server\share
80+
return Some(unsafe { UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)) });
8881
}
82+
_ => {}
83+
}
84+
} else if let [c, b':', ..] = path {
85+
// C:
86+
if is_valid_drive_letter(*c) {
87+
return Some(Disk(c.to_ascii_uppercase()));
8988
}
90-
return None;
9189
}
90+
None
9291
}
9392

9493
/// Returns the first two path components with predicate `f`.

0 commit comments

Comments
 (0)