diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index ca9fc0bc8..66981e823 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,5 +1,8 @@ Changes since 4.3 ALPHA1 ------------------- +* [HTTPCLIENT-1319] InetAddressUtils.isIPv6HexCompressedAddress does not detect excess groups + Contributed Sebastian Bazley . + * [HTTPCLIENT-1317] InetAddressUtils should handle IPv6 Addresses with Embedded IPv4 Addresses Contributed Sebastian Bazley . diff --git a/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java b/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java index e8e158db7..874f1b82e 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/InetAddressUtils.java @@ -62,6 +62,20 @@ public class InetAddressUtils { "::" + "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields + /* + * The above pattern is not totally rigorous as it allows for more than 7 hex fields in total + */ + private static final char COLON_CHAR = ':'; + + // Must not have more than 7 colons (i.e. 8 fields) + private static final int MAX_COLON_COUNT = 7; + + /** + * Checks whether the parameter is a valid IPv4 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid IPv4 address + */ public static boolean isIPv4Address(final String input) { return IPV4_PATTERN.matcher(input).matches(); } @@ -70,14 +84,38 @@ public class InetAddressUtils { return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches(); } + /** + * Checks whether the parameter is a valid standard (non-compressed) IPv6 address + * + * @param input the address string to check for validity + * @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(); } + /** + * Checks whether the parameter is a valid compressed IPv6 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid compressed IPv6 address + */ public static boolean isIPv6HexCompressedAddress(final String input) { - return IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches(); + 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(); } + /** + * Checks whether the parameter is a valid IPv6 address (including compressed). + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid standard or compressed IPv6 address + */ public static boolean isIPv6Address(final String input) { return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input); } diff --git a/httpclient/src/test/java/org/apache/http/conn/util/TestInetAddressUtils.java b/httpclient/src/test/java/org/apache/http/conn/util/TestInetAddressUtils.java index f181739cd..6749bdab5 100644 --- a/httpclient/src/test/java/org/apache/http/conn/util/TestInetAddressUtils.java +++ b/httpclient/src/test/java/org/apache/http/conn/util/TestInetAddressUtils.java @@ -59,6 +59,7 @@ public class TestInetAddressUtils { Assert.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("2001:0db8::1428:57ab")); Assert.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("2001:db8::1428:57ab")); Assert.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("::1")); + Assert.assertTrue(InetAddressUtils.isIPv6HexCompressedAddress("::")); // http://tools.ietf.org/html/rfc4291#section-2.2 } @Test @@ -70,15 +71,15 @@ public class TestInetAddressUtils { Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress(":1")); Assert.assertFalse(InetAddressUtils.isIPv6Address("2001:0db8::0000::57ab")); // Cannot have two contractions Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1:2:3:4:5:6:7::9")); // too many fields before :: + Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1::3:4:5:6:7:8:9")); // too many fields after :: Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("::3:4:5:6:7:8:9")); // too many fields after :: } @Test - @org.junit.Ignore // Test HTTPCLIENT-1319 public void testInvalidIPv6AddressIncorrectGroupCount() { - Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("::")); // not enough fields - Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1::2:3:4:5:6:7:8")); // too many fields + Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1:2::4:5:6:7:8:9")); // too many fields in total + Assert.assertFalse(InetAddressUtils.isIPv6HexCompressedAddress("1:2:3:4:5:6::8:9")); // too many fields in total } @Test