diff --git a/CHANGES.rst b/CHANGES.rst index 45ba37e7fa..8ca49f6ce8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,13 @@ Common (#2152) [Miguel Caballer - @micafer] +- [Utils] Fix ``is_valid_ip_address`` raising ``ValueError`` instead of + returning ``False`` for an address containing an embedded null byte + (e.g. ``"1.2.3.4\x00"``). ``socket.inet_pton`` raises ``ValueError`` rather + than ``OSError`` in that case, which was not caught. + (#2185) + [Ashish - @Ashishjob] + Compute ~~~~~~~ diff --git a/libcloud/test/test_utils.py b/libcloud/test/test_utils.py index 49a480587f..7a8d084386 100644 --- a/libcloud/test/test_utils.py +++ b/libcloud/test/test_utils.py @@ -424,6 +424,9 @@ def test_is_valid_ip_address(self): "256.256.256.256", "0.567.567.567", "192.168.0.257", + # Embedded null byte makes inet_pton raise ValueError, not OSError + "192.168.1.100\x00", + "10.0.0.1\x00extra", ] valid_ipv6_addresses = [ @@ -436,6 +439,8 @@ def test_is_valid_ip_address(self): invalid_ipv6_addresses = [ "2607:f0d", "2607:f0d0:0004", + # Embedded null byte makes inet_pton raise ValueError, not OSError + "::1\x00", ] for address in valid_ipv4_addresses: diff --git a/libcloud/utils/networking.py b/libcloud/utils/networking.py index 349abac3de..4ce7bc6a11 100644 --- a/libcloud/utils/networking.py +++ b/libcloud/utils/networking.py @@ -76,6 +76,13 @@ def is_valid_ip_address(address, family=socket.AF_INET): :return: ``bool`` True if the provided address is valid. """ + # inet_pton handles an embedded null byte (e.g. "1.2.3.4\x00") + # inconsistently across interpreters -- CPython raises ValueError while + # PyPy silently accepts it -- and such a string is never a valid address, + # so reject it explicitly for consistent behaviour. + if "\x00" in address: + return False + try: socket.inet_pton(family, address) except OSError: