Skip to content

Commit 6e6e83e

Browse files
authored
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
1 parent c29f95a commit 6e6e83e

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
@@ -2326,7 +2326,7 @@ def with_hostmask(self):
23262326

23272327
@property
23282328
def is_unspecified(self):
2329-
return self._ip == 0 and self.network.is_unspecified
2329+
return super().is_unspecified and self.network.is_unspecified
23302330

23312331
@property
23322332
def is_loopback(self):

‎Lib/test/test_ipaddress.py‎

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

2498+
self.assertTrue(ipaddress.ip_interface('::/128').is_unspecified)
2499+
self.assertTrue(
2500+
ipaddress.ip_interface('::ffff:0.0.0.0/128').is_unspecified)
2501+
self.assertFalse(ipaddress.ip_interface('::/127').is_unspecified)
2502+
self.assertFalse(
2503+
ipaddress.ip_interface('::ffff:0.0.0.0/127').is_unspecified)
2504+
self.assertFalse(ipaddress.ip_interface('::1/128').is_unspecified)
2505+
24982506
self.assertEqual(True,
24992507
ipaddress.ip_network('2001::1/128').is_private)
25002508
self.assertEqual(True,
@@ -2588,6 +2596,17 @@ def testIpv4MappedProperties(self):
25882596
self.assertEqual(ipv4.is_link_local, ipv6.is_link_local)
25892597
self.assertEqual(ipv4.is_loopback, ipv6.is_loopback)
25902598

2599+
ipv4 = ipaddress.IPv4Interface(addr4)
2600+
ipv6 = ipaddress.IPv6Interface(f"::ffff:{addr4}")
2601+
2602+
self.assertEqual(ipv4.is_global, ipv6.is_global)
2603+
self.assertEqual(ipv4.is_private, ipv6.is_private)
2604+
self.assertEqual(ipv4.is_reserved, ipv6.is_reserved)
2605+
self.assertEqual(ipv4.is_multicast, ipv6.is_multicast)
2606+
self.assertEqual(ipv4.is_unspecified, ipv6.is_unspecified)
2607+
self.assertEqual(ipv4.is_link_local, ipv6.is_link_local)
2608+
self.assertEqual(ipv4.is_loopback, ipv6.is_loopback)
2609+
25912610
def testIpv4MappedPrivateCheck(self):
25922611
self.assertEqual(
25932612
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)