mirror of
https://github.com/python/cpython.git
synced 2025-10-02 13:22:19 +00:00
[3.14] gh-128840: Limit the number of parts in IPv6 address parsing (GH-128841) (#134610)
gh-128840: Limit the number of parts in IPv6 address parsing (GH-128841)
GH-128840: Limit the number of parts in IPv6 address parsing
Limit length of IP address string to 39
---------
(cherry picked from commit 47f1161d3a
)
Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
This commit is contained in:
parent
38a38243b7
commit
576177d4b3
3 changed files with 22 additions and 2 deletions
|
@ -1660,8 +1660,16 @@ class _BaseV6:
|
||||||
"""
|
"""
|
||||||
if not ip_str:
|
if not ip_str:
|
||||||
raise AddressValueError('Address cannot be empty')
|
raise AddressValueError('Address cannot be empty')
|
||||||
|
if len(ip_str) > 39:
|
||||||
|
msg = ("At most 39 characters expected in "
|
||||||
|
f"{ip_str[:14]!r}({len(ip_str)-28} chars elided){ip_str[-14:]!r}")
|
||||||
|
raise AddressValueError(msg)
|
||||||
|
|
||||||
parts = ip_str.split(':')
|
# We want to allow more parts than the max to be 'split'
|
||||||
|
# to preserve the correct error message when there are
|
||||||
|
# too many parts combined with '::'
|
||||||
|
_max_parts = cls._HEXTET_COUNT + 1
|
||||||
|
parts = ip_str.split(':', maxsplit=_max_parts)
|
||||||
|
|
||||||
# An IPv6 address needs at least 2 colons (3 parts).
|
# An IPv6 address needs at least 2 colons (3 parts).
|
||||||
_min_parts = 3
|
_min_parts = 3
|
||||||
|
@ -1681,7 +1689,6 @@ class _BaseV6:
|
||||||
# An IPv6 address can't have more than 8 colons (9 parts).
|
# An IPv6 address can't have more than 8 colons (9 parts).
|
||||||
# The extra colon comes from using the "::" notation for a single
|
# The extra colon comes from using the "::" notation for a single
|
||||||
# leading or trailing zero part.
|
# leading or trailing zero part.
|
||||||
_max_parts = cls._HEXTET_COUNT + 1
|
|
||||||
if len(parts) > _max_parts:
|
if len(parts) > _max_parts:
|
||||||
msg = "At most %d colons permitted in %r" % (_max_parts-1, ip_str)
|
msg = "At most %d colons permitted in %r" % (_max_parts-1, ip_str)
|
||||||
raise AddressValueError(msg)
|
raise AddressValueError(msg)
|
||||||
|
|
|
@ -397,6 +397,17 @@ class AddressTestCase_v6(BaseTestCase, CommonTestMixin_v6):
|
||||||
# A trailing IPv4 address is two parts
|
# A trailing IPv4 address is two parts
|
||||||
assertBadSplit("10:9:8:7:6:5:4:3:42.42.42.42%scope")
|
assertBadSplit("10:9:8:7:6:5:4:3:42.42.42.42%scope")
|
||||||
|
|
||||||
|
def test_bad_address_split_v6_too_long(self):
|
||||||
|
def assertBadSplit(addr):
|
||||||
|
msg = r"At most 39 characters expected in %s"
|
||||||
|
with self.assertAddressError(msg, repr(re.escape(addr[:14]))):
|
||||||
|
ipaddress.IPv6Address(addr)
|
||||||
|
|
||||||
|
# Long IPv6 address
|
||||||
|
long_addr = ("0:" * 10000) + "0"
|
||||||
|
assertBadSplit(long_addr)
|
||||||
|
assertBadSplit(long_addr + "%zoneid")
|
||||||
|
|
||||||
def test_bad_address_split_v6_too_many_parts(self):
|
def test_bad_address_split_v6_too_many_parts(self):
|
||||||
def assertBadSplit(addr):
|
def assertBadSplit(addr):
|
||||||
msg = "Exactly 8 parts expected without '::' in %r"
|
msg = "Exactly 8 parts expected without '::' in %r"
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Short-circuit the processing of long IPv6 addresses early in :mod:`ipaddress` to prevent excessive
|
||||||
|
memory consumption and a minor denial-of-service.
|
Loading…
Add table
Add a link
Reference in a new issue