Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-96035: Make urllib.parse.urlparse reject non-numeric ports #98273

Merged
merged 14 commits into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -1199,6 +1202,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 @@ -1132,15 +1131,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.