From b550884e646ed99b93c44ad34fce67015fe52464 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 3 Aug 2020 11:59:23 +0200 Subject: [PATCH] Resolve hash collisions for IPv4Interface and IPv6Interface The __hash__() methods of classes IPv4Interface and IPv6Interface had issue of generating constant hash values of 32 and 128 respectively causing hash collisions. The fix uses the hash() function to generate hash values for the objects instead of XOR operation Fixes: https://github.com/phihag/ipaddress/issues/55 --- ipaddress.py | 4 ++-- test_ipaddress.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ipaddress.py b/ipaddress.py index 3e6f9e4..19dfc4c 100644 --- a/ipaddress.py +++ b/ipaddress.py @@ -1536,7 +1536,7 @@ def __lt__(self, other): return False def __hash__(self): - return self._ip ^ self._prefixlen ^ int(self.network.network_address) + return hash((self._ip, self._prefixlen, int(self.network.network_address))) __reduce__ = _IPAddressBase.__reduce__ @@ -2229,7 +2229,7 @@ def __lt__(self, other): return False def __hash__(self): - return self._ip ^ self._prefixlen ^ int(self.network.network_address) + return hash((self._ip, self._prefixlen, int(self.network.network_address))) __reduce__ = _IPAddressBase.__reduce__ diff --git a/test_ipaddress.py b/test_ipaddress.py index a1721b8..6147b7f 100644 --- a/test_ipaddress.py +++ b/test_ipaddress.py @@ -2131,6 +2131,18 @@ def testsixtofour(self): sixtofouraddr.sixtofour) self.assertFalse(bad_addr.sixtofour) + # issue41004 Hash collisions in IPv4Interface and IPv6Interface + def testV4HashIsNotConstant(self): + ipv4_address1 = ipaddress.IPv4Interface("1.2.3.4") + ipv4_address2 = ipaddress.IPv4Interface("2.3.4.5") + self.assertNotEqual(ipv4_address1.__hash__(), ipv4_address2.__hash__()) + + # issue41004 Hash collisions in IPv4Interface and IPv6Interface + def testV6HashIsNotConstant(self): + ipv6_address1 = ipaddress.IPv6Interface("2001:658:22a:cafe:200:0:0:1") + ipv6_address2 = ipaddress.IPv6Interface("2001:658:22a:cafe:200:0:0:2") + self.assertNotEqual(ipv6_address1.__hash__(), ipv6_address2.__hash__()) + # Monkey-patch test runner if not hasattr(BaseTestCase, 'assertRaisesRegex'):