Skip to content

Commit 1cc36c0

Browse files
author
bors-servo
authored
Auto merge of #469 - sfackler:backslash-path, r=SimonSapin
Escape backslash in special URL path components Closes #468 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/469) <!-- Reviewable:end -->
2 parents a07eac0 + 85af99e commit 1cc36c0

File tree

6 files changed

+32
-4
lines changed

6 files changed

+32
-4
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
name = "url"
44
# When updating version, also modify html_root_url in the lib.rs
5-
version = "1.7.1"
5+
version = "1.7.2"
66
authors = ["The rust-url developers"]
77

88
description = "URL library for Rust, based on the WHATWG URL Standard"

percent_encoding/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "percent-encoding"
3-
version = "1.0.1"
3+
version = "1.0.2"
44
authors = ["The rust-url developers"]
55
description = "Percent encoding and decoding"
66
repository = "https://github.com/servo/rust-url/"

percent_encoding/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ define_encode_set! {
140140
/// space, double quote ("), hash (#), inequality qualifiers (<), (>), backtick (`),
141141
/// question mark (?), and curly brackets ({), (}), percent sign (%), forward slash (/) are
142142
/// encoded.
143+
///
144+
/// # Note
145+
///
146+
/// For [special URLs](https://url.spec.whatwg.org/#is-special), the backslash (\) character should
147+
/// additionally be escaped, but that is *not* included in this encode set.
143148
pub PATH_SEGMENT_ENCODE_SET = [DEFAULT_ENCODE_SET] | {'%', '/'}
144149
}
145150

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ assert_eq!(css_url.as_str(), "http://servo.github.io/rust-url/main.css");
112112
#[cfg(feature="heapsize")] #[macro_use] extern crate heapsize;
113113

114114
pub extern crate idna;
115+
#[macro_use]
115116
pub extern crate percent_encoding;
116117

117118
use encoding::EncodingOverride;

src/parser.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ use percent_encoding::{
2222
PATH_SEGMENT_ENCODE_SET
2323
};
2424

25+
define_encode_set! {
26+
// The backslash (\) character is treated as a path separator in special URLs
27+
// so it needs to be additionally escaped in that case.
28+
pub SPECIAL_PATH_SEGMENT_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'\\'}
29+
}
30+
2531
pub type ParseResult<T> = Result<T, ParseError>;
2632

2733
macro_rules! simple_enum_error {
@@ -1011,8 +1017,13 @@ impl<'a> Parser<'a> {
10111017
_ => {
10121018
self.check_url_code_point(c, &input);
10131019
if self.context == Context::PathSegmentSetter {
1014-
self.serialization.extend(utf8_percent_encode(
1015-
utf8_c, PATH_SEGMENT_ENCODE_SET));
1020+
if scheme_type.is_special() {
1021+
self.serialization.extend(utf8_percent_encode(
1022+
utf8_c, SPECIAL_PATH_SEGMENT_ENCODE_SET));
1023+
} else {
1024+
self.serialization.extend(utf8_percent_encode(
1025+
utf8_c, PATH_SEGMENT_ENCODE_SET));
1026+
}
10161027
} else {
10171028
self.serialization.extend(utf8_percent_encode(
10181029
utf8_c, DEFAULT_ENCODE_SET));

tests/unit.rs

+11
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ fn new_directory_paths() {
109109
}
110110
}
111111

112+
#[test]
113+
fn path_backslash_fun() {
114+
let mut special_url = "http://foobar.com".parse::<Url>().unwrap();
115+
special_url.path_segments_mut().unwrap().push("foo\\bar");
116+
assert_eq!(special_url.as_str(), "http://foobar.com/foo%5Cbar");
117+
118+
let mut nonspecial_url = "thing://foobar.com".parse::<Url>().unwrap();
119+
nonspecial_url.path_segments_mut().unwrap().push("foo\\bar");
120+
assert_eq!(nonspecial_url.as_str(), "thing://foobar.com/foo\\bar");
121+
}
122+
112123
#[test]
113124
fn from_str() {
114125
assert!("http://testing.com/this".parse::<Url>().is_ok());

0 commit comments

Comments
 (0)