Skip to content

Commit

Permalink
Fix is_loopback() for IPv4-mapped loopbacks
Browse files Browse the repository at this point in the history
While properties like is_private account for IPv4-mapped IPv6 addresses,
such as for example:

    >>> ipaddress.ip_address("192.168.0.1").is_private
    True
    >>> ipaddress.ip_address("::ffff:192.168.0.1").is_private
    True
...the same doesn't currently apply to the is_loopback property:
    >>> ipaddress.ip_address("127.0.0.1").is_loopback
    True
    >>> ipaddress.ip_address("::ffff:127.0.0.1").is_loopback
    False

At minimum, this inconsistency between different properties is
counter-intuitive. Moreover, ::ffff:127.0.0.0/112 is for all intents and
purposes a loopback address, and should be treated as such.

For the record, this will now match the behavior of other languages such
as Rust, Go and .NET, cf. rust-lang/rust#69772.
  • Loading branch information
paravoid committed Apr 5, 2024
1 parent 9ceaee7 commit 96b88df
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -2142,6 +2142,9 @@ def is_loopback(self):
RFC 2373 2.5.3.
"""
ipv4_mapped = self.ipv4_mapped
if ipv4_mapped is not None:
return ipv4_mapped.is_loopback
return self._ip == 1

@property
Expand Down Expand Up @@ -2258,7 +2261,7 @@ def is_unspecified(self):

@property
def is_loopback(self):
return self._ip == 1 and self.network.is_loopback
return super().is_loopback and self.network.is_loopback


class IPv6Network(_BaseV6, _BaseNetwork):
Expand Down

0 comments on commit 96b88df

Please sign in to comment.