Skip to content

Commit 23e23d9

Browse files
committed
gh-105704: Disallow IPv6 URLs with invalid prefix/suffix
1 parent a5440d4 commit 23e23d9

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

Lib/test/test_urlparse.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,16 +1402,29 @@ def test_issue14072(self):
14021402
self.assertEqual(p2.path, '+31641044153')
14031403

14041404
def test_invalid_bracketed_hosts(self):
1405-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[192.0.2.146]/Path?Query')
1406-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[important.com:8000]/Path?Query')
1407-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123r.IP]/Path?Query')
1408-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v12ae]/Path?Query')
1409-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v.IP]/Path?Query')
1410-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123.]/Path?Query')
1411-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v]/Path?Query')
1412-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query')
1413-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query')
1414-
self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path')
1405+
cases = [
1406+
'Scheme://user@[192.0.2.146]/Path?Query',
1407+
'Scheme://user@[important.com:8000]/Path?Query',
1408+
'Scheme://user@[v123r.IP]/Path?Query',
1409+
'Scheme://user@[v12ae]/Path?Query',
1410+
'Scheme://user@[v.IP]/Path?Query',
1411+
'Scheme://user@[v123.]/Path?Query',
1412+
'Scheme://user@[v]/Path?Query',
1413+
'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query',
1414+
'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query',
1415+
'Scheme://user@]v6a.ip[/Path',
1416+
'Scheme://user@[v6a.ip/path?query',
1417+
'Scheme://user@v6a.ip]/path?query',
1418+
'Scheme://user@prefix.[v6a.ip]/path?query',
1419+
'Scheme://user@[v6a.ip].suffix/path?query',
1420+
]
1421+
1422+
for case in cases:
1423+
with self.subTest(case=case):
1424+
with self.assertRaises(ValueError):
1425+
urllib.parse.urlsplit(case).hostname
1426+
with self.assertRaises(ValueError):
1427+
urllib.parse.urlparse(case).hostname
14151428

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

Lib/urllib/parse.py

Lines changed: 7 additions & 5 deletions
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:
@@ -504,9 +509,6 @@ def _urlsplit(url, scheme=None, allow_fragments=True):
504509
if (('[' in netloc and ']' not in netloc) or
505510
(']' in netloc and '[' not in netloc)):
506511
raise ValueError("Invalid IPv6 URL")
507-
if '[' in netloc and ']' in netloc:
508-
bracketed_host = netloc.partition('[')[2].partition(']')[0]
509-
_check_bracketed_host(bracketed_host)
510512
if allow_fragments and '#' in url:
511513
url, fragment = url.split('#', 1)
512514
if '?' in url:

0 commit comments

Comments
 (0)