diff --git a/url/src/parser.rs b/url/src/parser.rs index 6ccfa9b46..589b597d0 100644 --- a/url/src/parser.rs +++ b/url/src/parser.rs @@ -1397,6 +1397,9 @@ impl Parser<'_> { let segment_start = path_start + slash_position + 1; // Don’t pop a Windows drive letter if !(scheme_type.is_file() + // It's only a drive letter if it's at the beginning of a path, + // e.g. in `/a/c:` the `c:` isn't one because it's not at the start of a path. + && segment_start == path_start + 1 && is_normalized_windows_drive_letter(&self.serialization[segment_start..])) { self.serialization.truncate(segment_start); diff --git a/url/tests/unit.rs b/url/tests/unit.rs index faeb7c5f4..8702302ca 100644 --- a/url/tests/unit.rs +++ b/url/tests/unit.rs @@ -1351,6 +1351,25 @@ fn test_file_with_drive_and_path() { assert_eq!(url2.to_string(), "file:///p:/a"); } +#[test] +fn test_file_base_drive_shaped_segment() { + let testcases = [ + ("file:a/c:", "..", "file:///"), + ( + "file:a/c:", + "../example-1.0-py3-none-any.whl", + "file:///example-1.0-py3-none-any.whl", + ), + ("file:///w:/c:", "file:..", "file:///w:/"), + ("file:///c:/..", "", "file:///c:/"), + ]; + + for (base, reference, expected) in testcases { + let base = Url::parse(base).unwrap(); + assert_eq!(base.join(reference).unwrap().as_str(), expected); + } +} + #[cfg(feature = "std")] #[test] fn issue_864() {