Skip to content

Commit 85859f0

Browse files
authored
net.urllib: reject backslashes in URL authorities (#27947)
1 parent 88c5db7 commit 85859f0

2 files changed

Lines changed: 24 additions & 3 deletions

File tree

vlib/net/urllib/urllib.v

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn should_escape(c u8, mode EncodingMode) bool {
5151
// we could possibly allow, and parse will reject them if we
5252
// escape them (because hosts can`t use %-encoding for
5353
// ASCII bytes).
54-
if c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`,
54+
if c in [`!`, `$`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`,
5555
`"`] {
5656
return false
5757
}
@@ -203,7 +203,7 @@ fn unescape(s_ string, mode EncodingMode) !string {
203203
else {
204204
if (mode == .encode_host || mode == .encode_zone) && s[i] < 0x80
205205
&& should_escape(s[i], mode) {
206-
error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
206+
return error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
207207
}
208208
i++
209209
}
@@ -1025,7 +1025,7 @@ pub fn valid_userinfo(s string) bool {
10251025
continue
10261026
}
10271027
match r {
1028-
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`,
1028+
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`,
10291029
`@` {
10301030
continue
10311031
}

vlib/net/urllib/urllib_test.v

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,27 @@ fn test_parse_authority() {
140140
}
141141
}
142142

143+
fn test_parse_rejects_backslash_in_authority() {
144+
invalid_urls := [
145+
r'http://127.0.0.1\@google.com/',
146+
r'http://user@google.com\path',
147+
r'http://google.com\path',
148+
]
149+
for url in invalid_urls {
150+
if _ := urllib.parse(url) {
151+
assert false, 'parser must reject "${url}"'
152+
}
153+
}
154+
}
155+
156+
fn test_parse_allows_apostrophe_in_authority() {
157+
url := urllib.parse("http://o'connor@example'host/")!
158+
assert url.host == "example'host"
159+
if user := url.user {
160+
assert user.username == "o'connor"
161+
}
162+
}
163+
143164
fn test_parse_slashes() {
144165
assert urllib.parse('/')!.str() == '/'
145166
assert urllib.parse('//')!.str() == '//'

0 commit comments

Comments
 (0)