From c6859926f3417f7f976b1c38e92fbd817137ce14 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 28 May 2025 18:24:24 +0300 Subject: [PATCH] gh-128840: Fix parsing long IPv6 addresses with embedded IPv4 address (GH-134836) (cherry picked from commit d83576bf48d07d5e29d5d171c4e25afb048622aa) Co-authored-by: Serhiy Storchaka --- Lib/ipaddress.py | 10 ++++++---- Lib/test/test_ipaddress.py | 19 +++++++++++++++++-- ...-05-28-15-53-27.gh-issue-128840.Nur2pB.rst | 1 + 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 7e8066fdb7108b..f57833ecc90768 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1648,10 +1648,12 @@ 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) + 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}") # We want to allow more parts than the max to be 'split' # to preserve the correct error message when there are diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 0f5550035104b7..b76cecaeed225c 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -391,14 +391,16 @@ def assertBadSplit(addr): 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]))): + msg = r"At most 45 characters expected in '%s" + with self.assertAddressError(msg, re.escape(addr[:45])): 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): @@ -2172,6 +2174,11 @@ def testIPv6AddressTooLarge(self): 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('::FFFF:192.0.2.1%scope'), ipaddress.ip_address('::FFFF:c000:201%scope')) self.assertEqual(ipaddress.ip_address('FFFF::192.0.2.1%scope'), @@ -2184,6 +2191,10 @@ def testIPv6AddressTooLarge(self): ipaddress.ip_address('::FFFF:c000:201%scope')) self.assertNotEqual(ipaddress.ip_address('FFFF::192.0.2.1'), ipaddress.ip_address('FFFF::c000:201%scope')) + 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) @@ -2568,6 +2579,10 @@ def testCompressIPv6Address(self): '::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:255.255.255.255/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( diff --git a/Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst b/Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst new file mode 100644 index 00000000000000..faff433aa4b86e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-28-15-53-27.gh-issue-128840.Nur2pB.rst @@ -0,0 +1 @@ +Fix parsing long IPv6 addresses with embedded IPv4 address.