]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-128840: Limit the number of parts in IPv6 address parsing (GH-128841) ...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 26 May 2025 03:34:44 +0000 (05:34 +0200)
committerGitHub <noreply@github.com>
Mon, 26 May 2025 03:34:44 +0000 (20:34 -0700)
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 <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>
Lib/ipaddress.py
Lib/test/test_ipaddress.py
Misc/NEWS.d/next/Security/2025-01-14-11-19-07.gh-issue-128840.M1doZW.rst [new file with mode: 0644]

index 6d0a103f2680390c93b61d508ad3e86ac4c1ed3c..4cedf936a19979c84b92a81d3cad7348af231081 100644 (file)
@@ -1664,8 +1664,16 @@ class _BaseV6:
         """
         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 @@ class _BaseV6:
         # 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)
index 7162b158bd32b4e84cd81e73df14a807a9ebc5d9..b1778600c2f5a76b44844ca690f0a3deae47192c 100644 (file)
@@ -389,6 +389,17 @@ class AddressTestCase_v6(BaseTestCase, CommonTestMixin_v6):
         # 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 (file)
index 0000000..b57ec3e
--- /dev/null
@@ -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.