Skip to content

Commit 3d41382

Browse files
committed
Make sure we don't remove a windows drive slash when shortening a path.
1 parent 6f78868 commit 3d41382

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

src/parser.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -1212,13 +1212,12 @@ impl<'a> Parser<'a> {
12121212
| ".%2E" => {
12131213
debug_assert!(self.serialization.as_bytes()[segment_start - 1] == b'/');
12141214
self.serialization.truncate(segment_start);
1215-
// Do not remove the root slash
1216-
if self.serialization.ends_with("/") && path_start + 1 < segment_start {
1215+
if self.serialization.ends_with("/")
1216+
&& Parser::last_slash_can_be_removed(&self.serialization, path_start)
1217+
{
12171218
self.serialization.pop();
1218-
self.shorten_path(scheme_type, path_start);
1219-
} else {
1220-
self.shorten_path(scheme_type, path_start);
12211219
}
1220+
self.shorten_path(scheme_type, path_start);
12221221

12231222
// and then if neither c is U+002F (/), nor url is special and c is U+005C (\), append the empty string to url’s path.
12241223
if ends_with_slash && !self.serialization.ends_with("/") {
@@ -1263,6 +1262,18 @@ impl<'a> Parser<'a> {
12631262
input
12641263
}
12651264

1265+
fn last_slash_can_be_removed(serialization: &String, path_start: usize) -> bool {
1266+
let url_before_segment = &serialization[..serialization.len() - 1];
1267+
if let Some(segment_before_start) = url_before_segment.rfind("/") {
1268+
// Do not remove the root slash
1269+
segment_before_start >= path_start
1270+
// Or a windows drive letter slash
1271+
&& !path_starts_with_windows_drive_letter(&serialization[segment_before_start..])
1272+
} else {
1273+
false
1274+
}
1275+
}
1276+
12661277
/// https://url.spec.whatwg.org/#shorten-a-urls-path
12671278
fn shorten_path(&mut self, scheme_type: SchemeType, path_start: usize) {
12681279
// If path is empty, then return.
@@ -1535,8 +1546,18 @@ fn is_windows_drive_letter(segment: &str) -> bool {
15351546
segment.len() == 2 && starts_with_windows_drive_letter(segment)
15361547
}
15371548

1549+
/// Wether path starts with a root slash
1550+
/// and a windows drive letter eg: "/c:" or "/a:/"
1551+
fn path_starts_with_windows_drive_letter(s: &str) -> bool {
1552+
s.len() > 3
1553+
&& matches!(s.as_bytes()[0], b'/' | b'\\' | b'?' | b'#')
1554+
&& starts_with_windows_drive_letter(&s[1..])
1555+
}
1556+
15381557
fn starts_with_windows_drive_letter(s: &str) -> bool {
1539-
ascii_alpha(s.as_bytes()[0] as char) && matches!(s.as_bytes()[1], b':' | b'|')
1558+
ascii_alpha(s.as_bytes()[0] as char)
1559+
&& matches!(s.as_bytes()[1], b':' | b'|')
1560+
&& (s.len() == 2 || matches!(s.as_bytes()[2], b'/' | b'\\' | b'?' | b'#'))
15401561
}
15411562

15421563
/// https://url.spec.whatwg.org/#start-with-a-windows-drive-letter

0 commit comments

Comments
 (0)