https://github.com/python/cpython/commit/d4cf1fafafc673e6147ff9d28f66ac1b50637605
commit: d4cf1fafafc673e6147ff9d28f66ac1b50637605
branch: 3.12
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Yhg1s <tho...@python.org>
date: 2025-05-25T20:34:44-07:00
summary:

[3.12] gh-128840: Limit the number of parts in IPv6 address parsing (GH-128841) 
(#134612)

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 47f1161d3a2bec52b5b5e952150141709c247da2)

Co-authored-by: Seth Michael Larson <s...@python.org>
Co-authored-by: Hugo van Kemenade <1324225+hug...@users.noreply.github.com>
Co-authored-by: Serhiy Storchaka <storch...@gmail.com>
Co-authored-by: Gregory P. Smith <g...@krypto.org>

files:
A Misc/NEWS.d/next/Security/2025-01-14-11-19-07.gh-issue-128840.M1doZW.rst
M Lib/ipaddress.py
M Lib/test/test_ipaddress.py

diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py
index 6d0a103f268039..4cedf936a19979 100644
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -1664,8 +1664,16 @@ def _ip_int_from_string(cls, ip_str):
         """
         if not ip_str:
             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).
         _min_parts = 3
@@ -1685,7 +1693,6 @@ def _ip_int_from_string(cls, ip_str):
         # An IPv6 address can't have more than 8 colons (9 parts).
         # The extra colon comes from using the "::" notation for a single
         # leading or trailing zero part.
-        _max_parts = cls._HEXTET_COUNT + 1
         if len(parts) > _max_parts:
             msg = "At most %d colons permitted in %r" % (_max_parts-1, ip_str)
             raise AddressValueError(msg)
diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py
index 7162b158bd32b4..b1778600c2f5a7 100644
--- a/Lib/test/test_ipaddress.py
+++ b/Lib/test/test_ipaddress.py
@@ -389,6 +389,17 @@ def assertBadSplit(addr):
         # A trailing IPv4 address is two parts
         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 assertBadSplit(addr):
             msg = "Exactly 8 parts expected without '::' in %r"
diff --git 
a/Misc/NEWS.d/next/Security/2025-01-14-11-19-07.gh-issue-128840.M1doZW.rst 
b/Misc/NEWS.d/next/Security/2025-01-14-11-19-07.gh-issue-128840.M1doZW.rst
new file mode 100644
index 00000000000000..b57ec3e70dcc5f
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2025-01-14-11-19-07.gh-issue-128840.M1doZW.rst
@@ -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.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to