File gh-128840_parse-IPv6-with-emb-IPv4.patch of Package python3.39333

---
 Lib/ipaddress.py                                                        |   19 +++++++
 Lib/test/test_ipaddress.py                                              |   27 ++++++++++
 Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst |    1 
 3 files changed, 47 insertions(+)

Index: Python-3.6.15/Lib/ipaddress.py
===================================================================
--- Python-3.6.15.orig/Lib/ipaddress.py	2025-06-14 18:04:37.744525235 +0200
+++ Python-3.6.15/Lib/ipaddress.py	2025-06-14 18:07:47.727340693 +0200
@@ -1169,6 +1169,13 @@
         if not ip_str:
             raise AddressValueError('Address cannot be empty')
 
+        if len(ip_str) > 45:
+            shorten = ip_str
+            if len(shorten) > 100:
+                shorten = f'{ip_str[:45]}({len(ip_str)-90} chars elided){ip_str[-45:]}'
+            raise AddressValueError(f"At most 45 characters expected in "
+                                    f"{shorten!r}")
+
         octets = ip_str.split('.')
         if len(octets) != 4:
             raise AddressValueError("Expected 4 octets in %r" % ip_str)
@@ -1588,6 +1595,8 @@
     _HEXTET_COUNT = 8
     _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef')
     _max_prefixlen = IPV6LENGTH
+    # The longest valid IPv6 string is 39 chars, so 45 provides buffer.
+    _MAX_STR_LEN = 45
 
     # There are only a bunch of valid v6 netmasks, so we cache them all
     # when constructed (see _make_netmask()).
@@ -1630,6 +1639,16 @@
         if not ip_str:
             raise AddressValueError('Address cannot be empty')
 
+        # Add this general string length check at the beginning for consistency with IPv4
+        # and to catch extremely long invalid inputs before more complex parsing.
+        if len(ip_str) > cls._MAX_STR_LEN:
+            shorten = ip_str
+            # If the string is exceedingly long, elide characters for readability in the error message.
+            if len(shorten) > 100: # Arbitrary threshold for shortening
+                shorten = f'{ip_str[:45]}({len(ip_str)-90} chars elided){ip_str[-45:]}'
+            raise AddressValueError(f"At most {cls._MAX_STR_LEN} characters expected in "
+                                    f"{shorten!r}")
+
         parts = ip_str.split(':')
 
         # An IPv6 address needs at least 2 colons (3 parts).
Index: Python-3.6.15/Lib/test/test_ipaddress.py
===================================================================
--- Python-3.6.15.orig/Lib/test/test_ipaddress.py	2025-06-14 18:05:21.404942454 +0200
+++ Python-3.6.15/Lib/test/test_ipaddress.py	2025-06-14 18:05:43.150531465 +0200
@@ -314,6 +314,19 @@
         # A trailing IPv4 address is two parts
         assertBadSplit("10:9:8:7:6:5:4:3:42.42.42.42")
 
+    def test_bad_address_split_v6_too_long(self):
+        def assertBadSplit(addr):
+            msg = r"At most 45 characters expected in '.*?'"
+            with self.assertAddressError(msg):
+                ipaddress.IPv6Address(addr)
+
+        # Long IPv6 address
+        long_addr = ("0:" * 10000) + "0"
+        assertBadSplit(long_addr)
+        assertBadSplit(long_addr + "%zoneid")
+        assertBadSplit(long_addr + ":255.255.255.255")
+        assertBadSplit(long_addr + ":ffff:255.255.255.255")
+
     def test_bad_address_split_v6_too_many_parts(self):
         def assertBadSplit(addr):
             msg = r"Exactly \d+ parts expected without '::' in '.*?'"
@@ -1767,6 +1780,16 @@
         self.assertEqual(ipaddress.ip_address('FFFF::192.0.2.1'),
                          ipaddress.ip_address('FFFF::c000:201'))
 
+        self.assertEqual(ipaddress.ip_address('0000:0000:0000:0000:0000:FFFF:192.168.255.255'),
+                         ipaddress.ip_address('::ffff:c0a8:ffff'))
+        self.assertEqual(ipaddress.ip_address('FFFF:0000:0000:0000:0000:0000:192.168.255.255'),
+                         ipaddress.ip_address('ffff::c0a8:ffff'))
+
+        self.assertEqual(ipaddress.ip_address('0000:0000:0000:0000:0000:FFFF:192.168.255.255%scope'),
+                         ipaddress.ip_address('::ffff:c0a8:ffff%scope'))
+        self.assertEqual(ipaddress.ip_address('FFFF:0000:0000:0000:0000:0000:192.168.255.255%scope'),
+                         ipaddress.ip_address('ffff::c0a8:ffff%scope'))
+
     def testIPVersion(self):
         self.assertEqual(self.ipv4_address.version, 4)
         self.assertEqual(self.ipv6_address.version, 6)
@@ -2060,6 +2083,10 @@
             '::7:6:5:4:3:2:0': '0:7:6:5:4:3:2:0/128',
             '7:6:5:4:3:2:1::': '7:6:5:4:3:2:1:0/128',
             '0:6:5:4:3:2:1::': '0:6:5:4:3:2:1:0/128',
+            '0000:0000:0000:0000:0000:0000:255.255.255.255': '::ffff:ffff/128',
+            '0000:0000:0000:0000:0000:ffff:255.255.255.255': '::ffff:ffff:ffff/128',
+            'ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255':
+            'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128',
         }
         for uncompressed, compressed in list(test_addresses.items()):
             self.assertEqual(compressed, str(ipaddress.IPv6Interface(
Index: Python-3.6.15/Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ Python-3.6.15/Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst	2025-06-14 18:05:43.151050854 +0200
@@ -0,0 +1 @@
+Fix parsing long IPv6 addresses with embedded IPv4 address.
openSUSE Build Service is sponsored by