Skip to content

Commit 6f15ca8

Browse files
pythongh-96035: Make urllib.parse.urlparse reject non-numeric ports (python#98273)
Co-authored-by: Jelle Zijlstra <[email protected]>
1 parent 4ec9ed8 commit 6f15ca8

File tree

3 files changed

+18
-12
lines changed

3 files changed

+18
-12
lines changed

Lib/test/test_urlparse.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,16 @@ def test_attributes_bad_port(self):
653653
"""Check handling of invalid ports."""
654654
for bytes in (False, True):
655655
for parse in (urllib.parse.urlsplit, urllib.parse.urlparse):
656-
for port in ("foo", "1.5", "-1", "0x10"):
656+
for port in ("foo", "1.5", "-1", "0x10", "-0", "1_1", " 1", "1 ", "६"):
657657
with self.subTest(bytes=bytes, parse=parse, port=port):
658658
netloc = "www.example.net:" + port
659659
url = "http://" + netloc
660660
if bytes:
661-
netloc = netloc.encode("ascii")
662-
url = url.encode("ascii")
661+
if netloc.isascii() and port.isascii():
662+
netloc = netloc.encode("ascii")
663+
url = url.encode("ascii")
664+
else:
665+
continue
663666
p = parse(url)
664667
self.assertEqual(p.netloc, netloc)
665668
with self.assertRaises(ValueError):
@@ -1199,6 +1202,7 @@ def test_splitnport(self):
11991202
self.assertEqual(splitnport('127.0.0.1', 55), ('127.0.0.1', 55))
12001203
self.assertEqual(splitnport('parrot:cheese'), ('parrot', None))
12011204
self.assertEqual(splitnport('parrot:cheese', 55), ('parrot', None))
1205+
self.assertEqual(splitnport('parrot: +1_0 '), ('parrot', None))
12021206

12031207
def test_splitquery(self):
12041208
# Normal cases are exercised by other tests; ensure that we also

Lib/urllib/parse.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,11 @@ def hostname(self):
167167
def port(self):
168168
port = self._hostinfo[1]
169169
if port is not None:
170-
try:
171-
port = int(port, 10)
172-
except ValueError:
173-
message = f'Port could not be cast to integer value as {port!r}'
174-
raise ValueError(message) from None
175-
if not ( 0 <= port <= 65535):
170+
if port.isdigit() and port.isascii():
171+
port = int(port)
172+
else:
173+
raise ValueError(f"Port could not be cast to integer value as {port!r}")
174+
if not (0 <= port <= 65535):
176175
raise ValueError("Port out of range 0-65535")
177176
return port
178177

@@ -1132,15 +1131,15 @@ def splitnport(host, defport=-1):
11321131
def _splitnport(host, defport=-1):
11331132
"""Split host and port, returning numeric port.
11341133
Return given default port if no ':' found; defaults to -1.
1135-
Return numerical port if a valid number are found after ':'.
1134+
Return numerical port if a valid number is found after ':'.
11361135
Return None if ':' but not a valid number."""
11371136
host, delim, port = host.rpartition(':')
11381137
if not delim:
11391138
host = port
11401139
elif port:
1141-
try:
1140+
if port.isdigit() and port.isascii():
11421141
nport = int(port)
1143-
except ValueError:
1142+
else:
11441143
nport = None
11451144
return host, nport
11461145
return host, defport
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix bug in :func:`urllib.parse.urlparse` that causes certain port numbers
2+
containing whitespace, underscores, plus and minus signs, or non-ASCII digits to be
3+
incorrectly accepted.

0 commit comments

Comments
 (0)