Skip to content

Commit c3bc170

Browse files
committed
gh-105704: Disallow IPv6 URLs with invalid prefix/suffix
1 parent 96cbd1e commit c3bc170

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

Lib/test/test_urlparse.py

+23-10
Original file line numberDiff line numberDiff line change
@@ -1102,16 +1102,29 @@ def test_issue14072(self):
11021102
self.assertEqual(p2.path, '+31641044153')
11031103

11041104
def test_invalid_bracketed_hosts(self):
1105-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[192.0.2.146]/Path?Query')
1106-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[important.com:8000]/Path?Query')
1107-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123r.IP]/Path?Query')
1108-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v12ae]/Path?Query')
1109-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v.IP]/Path?Query')
1110-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123.]/Path?Query')
1111-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v]/Path?Query')
1112-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query')
1113-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query')
1114-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path')
1105+
cases = [
1106+
'Scheme://user@[192.0.2.146]/Path?Query',
1107+
'Scheme://user@[important.com:8000]/Path?Query',
1108+
'Scheme://user@[v123r.IP]/Path?Query',
1109+
'Scheme://user@[v12ae]/Path?Query',
1110+
'Scheme://user@[v.IP]/Path?Query',
1111+
'Scheme://user@[v123.]/Path?Query',
1112+
'Scheme://user@[v]/Path?Query',
1113+
'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query',
1114+
'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query',
1115+
'Scheme://user@]v6a.ip[/Path',
1116+
'Scheme://user@[v6a.ip/path?query',
1117+
'Scheme://[email protected]]/path?query',
1118+
'Scheme://user@prefix.[v6a.ip]/path?query',
1119+
'Scheme://user@[v6a.ip].suffix/path?query',
1120+
]
1121+
1122+
for case in cases:
1123+
with self.subTest(case=case):
1124+
with self.assertRaises(ValueError):
1125+
urllib.parse.urlsplit(case).hostname
1126+
with self.assertRaises(ValueError):
1127+
urllib.parse.urlparse(case).hostname
11151128

11161129
def test_splitting_bracketed_hosts(self):
11171130
p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query')

Lib/urllib/parse.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,15 @@ def _userinfo(self):
206206
def _hostinfo(self):
207207
netloc = self.netloc
208208
_, _, hostinfo = netloc.rpartition('@')
209-
_, have_open_br, bracketed = hostinfo.partition('[')
209+
bracket_prefix, have_open_br, bracketed = hostinfo.partition('[')
210210
if have_open_br:
211+
if bracket_prefix:
212+
raise ValueError('Invalid IPv6 URL')
211213
hostname, _, port = bracketed.partition(']')
212-
_, _, port = port.partition(':')
214+
_check_bracketed_host(hostname)
215+
bracket_suffix, _, port = port.partition(':')
216+
if bracket_suffix:
217+
raise ValueError('Invalid IPv6 URL')
213218
else:
214219
hostname, _, port = hostinfo.partition(':')
215220
if not port:
@@ -495,9 +500,6 @@ def urlsplit(url, scheme='', allow_fragments=True):
495500
if (('[' in netloc and ']' not in netloc) or
496501
(']' in netloc and '[' not in netloc)):
497502
raise ValueError("Invalid IPv6 URL")
498-
if '[' in netloc and ']' in netloc:
499-
bracketed_host = netloc.partition('[')[2].partition(']')[0]
500-
_check_bracketed_host(bracketed_host)
501503
if allow_fragments and '#' in url:
502504
url, fragment = url.split('#', 1)
503505
if '?' in url:

0 commit comments

Comments
 (0)