Skip to content

Commit

Permalink
gh-96035: Make urllib.parse.urlparse reject non-numeric ports (GH-98273)
Browse files Browse the repository at this point in the history
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
(cherry picked from commit 6f15ca8)

Co-authored-by: Ben Kallus <49924171+kenballus@users.noreply.github.com>
  • Loading branch information
miss-islington and kenballus authored Oct 20, 2022
1 parent ace6611 commit 1520f4e
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 12 deletions.
10 changes: 7 additions & 3 deletions Lib/test/test_urlparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,13 +653,16 @@ def test_attributes_bad_port(self):
"""Check handling of invalid ports."""
for bytes in (False, True):
for parse in (urllib.parse.urlsplit, urllib.parse.urlparse):
for port in ("foo", "1.5", "-1", "0x10"):
for port in ("foo", "1.5", "-1", "0x10", "-0", "1_1", " 1", "1 ", "६"):
with self.subTest(bytes=bytes, parse=parse, port=port):
netloc = "www.example.net:" + port
url = "http://" + netloc
if bytes:
netloc = netloc.encode("ascii")
url = url.encode("ascii")
if netloc.isascii() and port.isascii():
netloc = netloc.encode("ascii")
url = url.encode("ascii")
else:
continue
p = parse(url)
self.assertEqual(p.netloc, netloc)
with self.assertRaises(ValueError):
Expand Down Expand Up @@ -1195,6 +1198,7 @@ def test_splitnport(self):
self.assertEqual(splitnport('127.0.0.1', 55), ('127.0.0.1', 55))
self.assertEqual(splitnport('parrot:cheese'), ('parrot', None))
self.assertEqual(splitnport('parrot:cheese', 55), ('parrot', None))
self.assertEqual(splitnport('parrot: +1_0 '), ('parrot', None))

def test_splitquery(self):
# Normal cases are exercised by other tests; ensure that we also
Expand Down
17 changes: 8 additions & 9 deletions Lib/urllib/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,11 @@ def hostname(self):
def port(self):
port = self._hostinfo[1]
if port is not None:
try:
port = int(port, 10)
except ValueError:
message = f'Port could not be cast to integer value as {port!r}'
raise ValueError(message) from None
if not ( 0 <= port <= 65535):
if port.isdigit() and port.isascii():
port = int(port)
else:
raise ValueError(f"Port could not be cast to integer value as {port!r}")
if not (0 <= port <= 65535):
raise ValueError("Port out of range 0-65535")
return port

Expand Down Expand Up @@ -1125,15 +1124,15 @@ def splitnport(host, defport=-1):
def _splitnport(host, defport=-1):
"""Split host and port, returning numeric port.
Return given default port if no ':' found; defaults to -1.
Return numerical port if a valid number are found after ':'.
Return numerical port if a valid number is found after ':'.
Return None if ':' but not a valid number."""
host, delim, port = host.rpartition(':')
if not delim:
host = port
elif port:
try:
if port.isdigit() and port.isascii():
nport = int(port)
except ValueError:
else:
nport = None
return host, nport
return host, defport
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix bug in :func:`urllib.parse.urlparse` that causes certain port numbers
containing whitespace, underscores, plus and minus signs, or non-ASCII digits to be
incorrectly accepted.

0 comments on commit 1520f4e

Please sign in to comment.