Merge pull request #2185 from Ashishjob/fix-is-valid-ip-address-null-byte

Fix is_valid_ip_address raising ValueError on embedded null byte
diff --git a/CHANGES.rst b/CHANGES.rst
index 45ba37e..8ca49f6 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -11,6 +11,13 @@
   (#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 49a4805..7a8d084 100644
--- a/libcloud/test/test_utils.py
+++ b/libcloud/test/test_utils.py
@@ -424,6 +424,9 @@
             "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 @@
         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 349abac..4ce7bc6 100644
--- a/libcloud/utils/networking.py
+++ b/libcloud/utils/networking.py
@@ -76,6 +76,13 @@
 
     :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: