Skip to content

Commit eecb7ba

Browse files
committed
[3.15] gh-161100: Fix IPv6Interface.is_unspecified for IPv4-mapped addresses (GH-161101)
Defer to IPv6Address.is_unspecified, as the is_loopback override does, so ::ffff:0.0.0.0/128 interfaces are unspecified like the address. ANT-2026-DIFE27WF (cherry picked from commit 6e6e83e)
1 parent 89fe8f2 commit eecb7ba

3 files changed

Lines changed: 23 additions & 1 deletion

File tree

‎Lib/ipaddress.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2272,7 +2272,7 @@ def with_hostmask(self):
22722272

22732273
@property
22742274
def is_unspecified(self):
2275-
return self._ip == 0 and self.network.is_unspecified
2275+
return super().is_unspecified and self.network.is_unspecified
22762276

22772277
@property
22782278
def is_loopback(self):

‎Lib/test/test_ipaddress.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,6 +2447,14 @@ def testReservedIpv6(self):
24472447
self.assertEqual(False, ipaddress.ip_network('::1').is_unspecified)
24482448
self.assertEqual(False, ipaddress.ip_network('::/127').is_unspecified)
24492449

2450+
self.assertTrue(ipaddress.ip_interface('::/128').is_unspecified)
2451+
self.assertTrue(
2452+
ipaddress.ip_interface('::ffff:0.0.0.0/128').is_unspecified)
2453+
self.assertFalse(ipaddress.ip_interface('::/127').is_unspecified)
2454+
self.assertFalse(
2455+
ipaddress.ip_interface('::ffff:0.0.0.0/127').is_unspecified)
2456+
self.assertFalse(ipaddress.ip_interface('::1/128').is_unspecified)
2457+
24502458
self.assertEqual(True,
24512459
ipaddress.ip_network('2001::1/128').is_private)
24522460
self.assertEqual(True,
@@ -2536,6 +2544,17 @@ def testIpv4MappedProperties(self):
25362544
self.assertEqual(ipv4.is_link_local, ipv6.is_link_local)
25372545
self.assertEqual(ipv4.is_loopback, ipv6.is_loopback)
25382546

2547+
ipv4 = ipaddress.IPv4Interface(addr4)
2548+
ipv6 = ipaddress.IPv6Interface(f"::ffff:{addr4}")
2549+
2550+
self.assertEqual(ipv4.is_global, ipv6.is_global)
2551+
self.assertEqual(ipv4.is_private, ipv6.is_private)
2552+
self.assertEqual(ipv4.is_reserved, ipv6.is_reserved)
2553+
self.assertEqual(ipv4.is_multicast, ipv6.is_multicast)
2554+
self.assertEqual(ipv4.is_unspecified, ipv6.is_unspecified)
2555+
self.assertEqual(ipv4.is_link_local, ipv6.is_link_local)
2556+
self.assertEqual(ipv4.is_loopback, ipv6.is_loopback)
2557+
25392558
def testIpv4MappedPrivateCheck(self):
25402559
self.assertEqual(
25412560
True, ipaddress.ip_address('::ffff:192.168.1.1').is_private)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :attr:`!ipaddress.IPv6Interface.is_unspecified` returning ``False`` for
2+
the IPv4-mapped address ``::ffff:0.0.0.0``. It now gives the same result as
3+
:attr:`ipaddress.IPv6Address.is_unspecified`.

0 commit comments

Comments
 (0)