You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2022/05/04 06:47:45 UTC

[httpcomponents-core] branch master updated: Optimize InetAddressUtils#isIPv6*Address

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git


The following commit(s) were added to refs/heads/master by this push:
     new e7f48a619 Optimize InetAddressUtils#isIPv6*Address
e7f48a619 is described below

commit e7f48a6192294d1c2271fefb54285cdf8cb88941
Author: David Schlosnagle <da...@palantir.com>
AuthorDate: Tue May 3 17:52:37 2022 -0400

    Optimize InetAddressUtils#isIPv6*Address
    
    Check input colon count before performing IPv6 regex validation
---
 .../org/apache/hc/core5/net/InetAddressUtils.java  | 21 ++++++++------
 .../apache/hc/core5/net/TestInetAddressUtils.java  | 33 ++++++++++++++++++++++
 2 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/net/InetAddressUtils.java b/httpcore5/src/main/java/org/apache/hc/core5/net/InetAddressUtils.java
index a3aacbfa2..f3674574d 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/net/InetAddressUtils.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/net/InetAddressUtils.java
@@ -101,6 +101,17 @@ public class InetAddressUtils {
         return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches();
     }
 
+    static boolean hasValidIPv6ColonCount(final String input) {
+        int colonCount = 0;
+        for (int i = 0; i < input.length(); i++) {
+            if (input.charAt(i) == COLON_CHAR) {
+                colonCount++;
+            }
+        }
+        // IPv6 address must have at least 2 colons and not more than 7 (i.e. 8 fields)
+        return colonCount >= 2 && colonCount <= MAX_COLON_COUNT;
+    }
+
     /**
      * Checks whether the parameter is a valid standard (non-compressed) IPv6 address
      *
@@ -108,7 +119,7 @@ public class InetAddressUtils {
      * @return true if the input parameter is a valid standard (non-compressed) IPv6 address
      */
     public static boolean isIPv6StdAddress(final String input) {
-        return IPV6_STD_PATTERN.matcher(input).matches();
+        return hasValidIPv6ColonCount(input) && IPV6_STD_PATTERN.matcher(input).matches();
     }
 
     /**
@@ -118,13 +129,7 @@ public class InetAddressUtils {
      * @return true if the input parameter is a valid compressed IPv6 address
      */
     public static boolean isIPv6HexCompressedAddress(final String input) {
-        int colonCount = 0;
-        for(int i = 0; i < input.length(); i++) {
-            if (input.charAt(i) == COLON_CHAR) {
-                colonCount++;
-            }
-        }
-        return  colonCount <= MAX_COLON_COUNT && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
+        return hasValidIPv6ColonCount(input) && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
     }
 
     /**
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/net/TestInetAddressUtils.java b/httpcore5/src/test/java/org/apache/hc/core5/net/TestInetAddressUtils.java
index 9e73d5d91..7e6aa9905 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/net/TestInetAddressUtils.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/net/TestInetAddressUtils.java
@@ -57,11 +57,22 @@ public class TestInetAddressUtils {
         Assertions.assertTrue(InetAddressUtils.isIPv6StdAddress("2001:db8:0:0:0:0:1428:57ab"));
         Assertions.assertTrue(InetAddressUtils.isIPv6StdAddress("0:0:0:0:0:0:0:0"));
         Assertions.assertTrue(InetAddressUtils.isIPv6StdAddress("0:0:0:0:0:0:0:1"));
+
         Assertions.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("2001:0db8:0:0::1428:57ab"));
         Assertions.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("2001:0db8::1428:57ab"));
         Assertions.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("2001:db8::1428:57ab"));
         Assertions.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("::1"));
         Assertions.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("::")); // http://tools.ietf.org/html/rfc4291#section-2.2
+
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("2001:0db8:0000:0000:0000:0000:1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("2001:db8:0:0:0:0:1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("0:0:0:0:0:0:0:0"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("0:0:0:0:0:0:0:1"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("2001:0db8:0:0::1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("2001:0db8::1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("2001:db8::1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("::1"));
+        Assertions.assertTrue(InetAddressUtils.isIPv6Address("::")); // http://tools.ietf.org/html/rfc4291#section-2.2
     }
 
     @Test
@@ -71,6 +82,7 @@ public class TestInetAddressUtils {
         Assertions.assertFalse(InetAddressUtils.isIPv6StdAddress("0:0:0:0:0:0:0:0:0")); // Too many
         Assertions.assertFalse(InetAddressUtils.isIPv6StdAddress("0:0:0:0:0:0:0")); // Too few
         Assertions.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress(":1"));
+        Assertions.assertFalse(InetAddressUtils.isIPv6Address(":1"));
         Assertions.assertFalse(InetAddressUtils.isIPv6Address("2001:0db8::0000::57ab")); // Cannot have two contractions
         Assertions.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1:2:3:4:5:6:7::9")); // too many fields before ::
         Assertions.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1::3:4:5:6:7:8:9")); // too many fields after ::
@@ -135,6 +147,27 @@ public class TestInetAddressUtils {
         Assertions.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1:2:3:4:5:6::8:9")); // too many fields in total
     }
 
+    @Test
+    public void testHasValidIPv6ColonCount() {
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount(""));
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount(":"));
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount("127.0.0.1"));
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount(":0"));
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount("0:"));
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount("1:2:3:4:5:6:7:8:"));
+        Assertions.assertFalse(InetAddressUtils.hasValidIPv6ColonCount("1:2:3:4:5:6:7:8:9"));
+
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("2001:0db8:0000:0000:0000:0000:1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("2001:db8:0:0:0:0:1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("0:0:0:0:0:0:0:0"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("0:0:0:0:0:0:0:1"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("2001:0db8:0:0::1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("2001:0db8::1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("2001:db8::1428:57ab"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("::1"));
+        Assertions.assertTrue(InetAddressUtils.hasValidIPv6ColonCount("::")); // http://tools.ietf.org/html/rfc4291#section-2.2
+    }
+
     @Test
     public void testValidIPv4MappedIPv6Address() {
         Assertions.assertTrue(InetAddressUtils.isIPv4MappedIPv64Address("::FFFF:1.2.3.4"));