Skip to content

Commit bb72b92

Browse files
sethmlarsonhugovkserhiy-storchakagpshead
authored andcommitted
pythongh-128840: Limit the number of parts in IPv6 address parsing (pythonGH-128841)
pythonGH-128840: Limit the number of parts in IPv6 address parsing Limit length of IP address string to 39 --------- (cherry picked from commit 47f1161) Co-authored-by: Seth Michael Larson <[email protected]> Co-authored-by: Hugo van Kemenade <[email protected]> Co-authored-by: Serhiy Storchaka <[email protected]> Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 6322edd commit bb72b92

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

Lib/ipaddress.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,8 +1649,16 @@ def _ip_int_from_string(cls, ip_str):
16491649
"""
16501650
if not ip_str:
16511651
raise AddressValueError('Address cannot be empty')
1652+
if len(ip_str) > 39:
1653+
msg = ("At most 39 characters expected in "
1654+
f"{ip_str[:14]!r}({len(ip_str)-28} chars elided){ip_str[-14:]!r}")
1655+
raise AddressValueError(msg)
16521656

1653-
parts = ip_str.split(':')
1657+
# We want to allow more parts than the max to be 'split'
1658+
# to preserve the correct error message when there are
1659+
# too many parts combined with '::'
1660+
_max_parts = cls._HEXTET_COUNT + 1
1661+
parts = ip_str.split(':', maxsplit=_max_parts)
16541662

16551663
# An IPv6 address needs at least 2 colons (3 parts).
16561664
_min_parts = 3
@@ -1670,7 +1678,6 @@ def _ip_int_from_string(cls, ip_str):
16701678
# An IPv6 address can't have more than 8 colons (9 parts).
16711679
# The extra colon comes from using the "::" notation for a single
16721680
# leading or trailing zero part.
1673-
_max_parts = cls._HEXTET_COUNT + 1
16741681
if len(parts) > _max_parts:
16751682
msg = "At most %d colons permitted in %r" % (_max_parts-1, ip_str)
16761683
raise AddressValueError(msg)

Lib/test/test_ipaddress.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,17 @@ def assertBadSplit(addr):
389389
# A trailing IPv4 address is two parts
390390
assertBadSplit("10:9:8:7:6:5:4:3:42.42.42.42%scope")
391391

392+
def test_bad_address_split_v6_too_long(self):
393+
def assertBadSplit(addr):
394+
msg = r"At most 39 characters expected in %s"
395+
with self.assertAddressError(msg, repr(re.escape(addr[:14]))):
396+
ipaddress.IPv6Address(addr)
397+
398+
# Long IPv6 address
399+
long_addr = ("0:" * 10000) + "0"
400+
assertBadSplit(long_addr)
401+
assertBadSplit(long_addr + "%zoneid")
402+
392403
def test_bad_address_split_v6_too_many_parts(self):
393404
def assertBadSplit(addr):
394405
msg = "Exactly 8 parts expected without '::' in %r"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Short-circuit the processing of long IPv6 addresses early in :mod:`ipaddress` to prevent excessive
2+
memory consumption and a minor denial-of-service.

0 commit comments

Comments
 (0)