diff options
author | Elliott Hughes <enh@google.com> | 2011-06-03 12:43:17 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2011-06-03 23:27:56 -0700 |
commit | fc041ff241f9a7556e72236f130de0215ecd17db (patch) | |
tree | 0f7bd89644f72779e4a23a21ef4d14432f711635 /luni | |
parent | 8f1bbe0b6549136be386d75edf70ed4daf8a25b0 (diff) | |
download | libcore-fc041ff241f9a7556e72236f130de0215ecd17db.zip libcore-fc041ff241f9a7556e72236f130de0215ecd17db.tar.gz libcore-fc041ff241f9a7556e72236f130de0215ecd17db.tar.bz2 |
Remove support for deprecated IPv4 address formats.
Bug: 4539262
Change-Id: Ic42173b7b06e8536e8c4331087720d7df1e1681a
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/main/java/java/net/InetAddress.java | 42 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/ForwardingOs.java | 2 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Os.java | 2 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Posix.java | 2 | ||||
-rw-r--r-- | luni/src/main/native/libcore_io_Posix.cpp | 11 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/net/InetAddressTest.java | 126 |
6 files changed, 112 insertions, 73 deletions
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java index 9009226..a6998ca 100644 --- a/luni/src/main/java/java/net/InetAddress.java +++ b/luni/src/main/java/java/net/InetAddress.java @@ -49,22 +49,10 @@ import static libcore.io.OsConstants.*; * depending on how the {@code InetAddress} was created. * * <h4>IPv4 numeric address formats</h4> - * <p>The {@code getAllByName} method accepts IPv4 addresses in the following forms: + * <p>The {@code getAllByName} method accepts IPv4 addresses in the "decimal-dotted-quad" form only: * <ul> * <li>{@code "1.2.3.4"} - 1.2.3.4 - * <li>{@code "1.2.3"} - 1.2.0.3 - * <li>{@code "1.2"} - 1.0.0.2 - * <li>{@code "16909060"} - 1.2.3.4 * </ul> - * <p>In the first three cases, each number is treated as an 8-bit value between 0 and 255. - * In the fourth case, the single number is treated as a 32-bit value representing the entire - * address. - * <p>Note that each numeric part can be expressed in decimal (as above) or hex. For example, - * {@code "0x01020304"} is equivalent to 1.2.3.4 and {@code "0xa.0xb.0xc.0xd"} is equivalent - * to 10.11.12.13. - * - * <p>Typically, only the four-dot decimal form ({@code "1.2.3.4"}) is ever used. Any method that - * <i>returns</i> a textual numeric address will use four-dot decimal form. * * <h4>IPv6 numeric address formats</h4> * <p>The {@code getAllByName} method accepts IPv6 addresses in the following forms (this text @@ -248,6 +236,10 @@ public class InetAddress implements Serializable { // Is it a numeric address? InetAddress result = parseNumericAddressNoThrow(host); if (result != null) { + result = disallowDeprecatedFormats(host, result); + if (result == null) { + throw new UnknownHostException("Deprecated IPv4 address format: " + host); + } return new InetAddress[] { result }; } @@ -264,6 +256,17 @@ public class InetAddress implements Serializable { } } + private static InetAddress disallowDeprecatedFormats(String address, InetAddress inetAddress) { + // Only IPv4 addresses are problematic. + if (!(inetAddress instanceof Inet4Address) || address.indexOf(':') != -1) { + return inetAddress; + } + // If inet_pton(3) can't parse it, it must have been a deprecated format. + // We need to return inet_pton(3)'s result to ensure that numbers assumed to be octal + // by getaddrinfo(3) are reinterpreted by inet_pton(3) as decimal. + return Libcore.os.inet_pton(AF_INET, address); + } + private static InetAddress parseNumericAddressNoThrow(String address) { // Accept IPv6 addresses (only) in square brackets for compatibility. if (address.startsWith("[") && address.endsWith("]") && address.indexOf(':') != -1) { @@ -276,14 +279,7 @@ public class InetAddress implements Serializable { addresses = Libcore.os.getaddrinfo(address, hints); } catch (GaiException ignored) { } - if (addresses == null) { - // For backwards compatibility, deal with address formats that - // getaddrinfo does not support. For example, 1.2.3, 1.3, and even 3 are - // valid IPv4 addresses according to the Java API. If getaddrinfo fails, - // try to use inet_aton. - return Libcore.os.inet_aton(address); - } - return addresses[0]; + return (addresses != null) ? addresses[0] : null; } /** @@ -484,7 +480,8 @@ public class InetAddress implements Serializable { * @hide used by frameworks/base to ensure that a getAllByName won't cause a DNS lookup. */ public static boolean isNumeric(String address) { - return parseNumericAddressNoThrow(address) != null; + InetAddress inetAddress = parseNumericAddressNoThrow(address); + return inetAddress != null && disallowDeprecatedFormats(address, inetAddress) != null; } /** @@ -500,6 +497,7 @@ public class InetAddress implements Serializable { return Inet6Address.LOOPBACK; } InetAddress result = parseNumericAddressNoThrow(numericAddress); + result = disallowDeprecatedFormats(numericAddress, result); if (result == null) { throw new IllegalArgumentException("Not a numeric address: " + numericAddress); } diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index 609beab..6acb544 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -70,7 +70,7 @@ public class ForwardingOs implements Os { public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptTimeval(fd, level, option); } public int getuid() { return os.getuid(); } public String if_indextoname(int index) { return os.if_indextoname(index); } - public InetAddress inet_aton(String address) { return os.inet_aton(address); } + public InetAddress inet_pton(int family, String address) { return os.inet_pton(family, address); } public InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException { return os.ioctlInetAddress(fd, cmd, interfaceName); } public int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException { return os.ioctlInt(fd, cmd, arg); } public boolean isatty(FileDescriptor fd) { return os.isatty(fd); } diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index 07d1464..acf72e9 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -62,7 +62,7 @@ public interface Os { public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException; public int getuid(); public String if_indextoname(int index); - public InetAddress inet_aton(String address); + public InetAddress inet_pton(int family, String address); public InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException; public int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException; public boolean isatty(FileDescriptor fd); diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index d6cdd89..6317e01 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -64,7 +64,7 @@ public final class Posix implements Os { public native StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException; public native int getuid(); public native String if_indextoname(int index); - public native InetAddress inet_aton(String address); + public native InetAddress inet_pton(int family, String address); public native InetAddress ioctlInetAddress(FileDescriptor fd, int cmd, String interfaceName) throws ErrnoException; public native int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException; public native boolean isatty(FileDescriptor fd); diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index 97a9399..687bd65 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -742,18 +742,19 @@ static jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) { return env->NewStringUTF(name); } -static jobject Posix_inet_aton(JNIEnv* env, jobject, jstring javaName) { +static jobject Posix_inet_pton(JNIEnv* env, jobject, jint family, jstring javaName) { ScopedUtfChars name(env, javaName); if (name.c_str() == NULL) { return NULL; } sockaddr_storage ss; memset(&ss, 0, sizeof(ss)); - sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss); - if (inet_aton(name.c_str(), &sin->sin_addr) == 0) { + // sockaddr_in and sockaddr_in6 are at the same address, so we can use either here. + void* dst = &reinterpret_cast<sockaddr_in*>(&ss)->sin_addr; + if (inet_pton(family, name.c_str(), dst) != 1) { return NULL; } - sin->sin_family = AF_INET; // inet_aton only supports IPv4. + ss.ss_family = family; return sockaddrToInetAddress(env, &ss, NULL); } @@ -1235,7 +1236,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructTimeval;"), NATIVE_METHOD(Posix, getuid, "()I"), NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"), - NATIVE_METHOD(Posix, inet_aton, "(Ljava/lang/String;)Ljava/net/InetAddress;"), + NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"), NATIVE_METHOD(Posix, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"), NATIVE_METHOD(Posix, ioctlInt, "(Ljava/io/FileDescriptor;ILlibcore/util/MutableInt;)I"), NATIVE_METHOD(Posix, isatty, "(Ljava/io/FileDescriptor;)Z"), diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java index 3b50df8..66e9f99 100644 --- a/luni/src/test/java/libcore/java/net/InetAddressTest.java +++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java @@ -19,10 +19,48 @@ package libcore.java.net; import java.net.InetAddress; import java.net.Inet4Address; import java.net.Inet6Address; +import java.net.UnknownHostException; public class InetAddressTest extends junit.framework.TestCase { private static final byte[] LOOPBACK6_BYTES = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + private static final String[] INVALID_IPv4_NUMERIC_ADDRESSES = new String[] { + // IPv4 addresses may not be surrounded by square brackets. + "[127.0.0.1]", + + // Trailing dots are not allowed. + "1.2.3.4.", + // Nor is any kind of trailing junk. + "1.2.3.4hello", + + // Out of range. + "256.2.3.4", + "1.256.3.4", + "1.2.256.4", + "1.2.3.256", + + // Deprecated. + "1.2.3", + "1.2", + "1", + "1234", + "0", // Single out the deprecated form of the ANY address. + + // Hex. + "0x1.0x2.0x3.0x4", + "0x7f.0x00.0x00.0x01", + "7f.0.0.1", + + // Octal. + "0177.00.00.01", // Historically, this would have been interpreted as 127.0.0.1. + + // Negative numbers. + "-1.0.0.1", + "1.-1.0.1", + "1.0.-1.1", + "1.0.0.-1", + }; + private static Inet6Address loopback6() throws Exception { return (Inet6Address) InetAddress.getByAddress(LOOPBACK6_BYTES); } @@ -36,44 +74,52 @@ public class InetAddressTest extends junit.framework.TestCase { assertEquals("/1.2.3.4", InetAddress.parseNumericAddress("1.2.3.4").toString()); // Regular IPv6. assertEquals("/2001:4860:800d::68", InetAddress.parseNumericAddress("2001:4860:800d::68").toString()); - // Weird IPv4 special cases. - assertEquals("/1.2.0.3", InetAddress.parseNumericAddress("1.2.3").toString()); - assertEquals("/1.0.0.2", InetAddress.parseNumericAddress("1.2").toString()); - assertEquals("/0.0.0.1", InetAddress.parseNumericAddress("1").toString()); - assertEquals("/0.0.4.210", InetAddress.parseNumericAddress("1234").toString()); // Optional square brackets around IPv6 addresses, including mapped IPv4. assertEquals("/2001:4860:800d::68", InetAddress.parseNumericAddress("[2001:4860:800d::68]").toString()); assertEquals("/127.0.0.1", InetAddress.parseNumericAddress("[::ffff:127.0.0.1]").toString()); + try { - // Actual IPv4 addresses may not be surrounded by square brackets. - assertEquals("/127.0.0.1", InetAddress.parseNumericAddress("[127.0.0.1]").toString()); - fail(); - } catch (IllegalArgumentException expected) { - } - try { - // Almost numeric but invalid... - InetAddress.parseNumericAddress("1."); + InetAddress.parseNumericAddress("example.com"); // Not numeric. fail(); } catch (IllegalArgumentException expected) { } - try { - // Not even close to numeric... - InetAddress.parseNumericAddress("www.google.com"); - fail(); - } catch (IllegalArgumentException expected) { + + for (String invalid : INVALID_IPv4_NUMERIC_ADDRESSES) { + try { + InetAddress.parseNumericAddress(invalid); + fail(invalid); + } catch (IllegalArgumentException expected) { + } } + // Strange special cases, for compatibility with InetAddress.getByName. assertTrue(InetAddress.parseNumericAddress(null).isLoopbackAddress()); assertTrue(InetAddress.parseNumericAddress("").isLoopbackAddress()); } - public void test_getLoopbackAddress() throws Exception { - assertTrue(InetAddress.getLoopbackAddress().isLoopbackAddress()); + public void test_isNumeric() throws Exception { + assertTrue(InetAddress.isNumeric("1.2.3.4")); + assertTrue(InetAddress.isNumeric("127.0.0.1")); + + assertFalse(InetAddress.isNumeric("example.com")); + + for (String invalid : INVALID_IPv4_NUMERIC_ADDRESSES) { + assertFalse(invalid, InetAddress.isNumeric(invalid)); + } } - public void test_0() throws Exception { - // The RI special-cases "0" for legacy IPv4 applications. - assertTrue(InetAddress.getByName("0").isAnyLocalAddress()); + public void test_getByName() throws Exception { + for (String invalid : INVALID_IPv4_NUMERIC_ADDRESSES) { + try { + InetAddress.getByName(invalid); + fail(invalid); + } catch (UnknownHostException expected) { + } + } + } + + public void test_getLoopbackAddress() throws Exception { + assertTrue(InetAddress.getLoopbackAddress().isLoopbackAddress()); } public void test_equals() throws Exception { @@ -82,10 +128,11 @@ public class InetAddressTest extends junit.framework.TestCase { assertTrue(loopback6().equals(localhost6())); assertFalse(addr.equals(loopback6())); - InetAddress addr3 = InetAddress.getByName("127.0.0"); - assertFalse(loopback6().equals(addr3)); - assertTrue(Inet4Address.LOOPBACK.equals(Inet4Address.LOOPBACK)); + + // http://b/4328294 - the scope id isn't included when comparing Inet6Address instances. + byte[] bs = new byte[16]; + assertEquals(Inet6Address.getByAddress("1", bs, 1), Inet6Address.getByAddress("2", bs, 2)); } public void test_getHostAddress() throws Exception { @@ -97,14 +144,12 @@ public class InetAddressTest extends junit.framework.TestCase { InetAddress aAddr = InetAddress.getByName("224.0.0.0"); assertEquals("224.0.0.0", aAddr.getHostAddress()); - aAddr = InetAddress.getByName("1"); - assertEquals("0.0.0.1", aAddr.getHostAddress()); - aAddr = InetAddress.getByName("1.1"); - assertEquals("1.0.0.1", aAddr.getHostAddress()); - - aAddr = InetAddress.getByName("1.1.1"); - assertEquals("1.1.0.1", aAddr.getHostAddress()); + try { + InetAddress.getByName("1"); + fail(); + } catch (UnknownHostException expected) { + } byte[] bAddr = { (byte) 0xFE, (byte) 0x80, (byte) 0x00, (byte) 0x00, @@ -155,11 +200,8 @@ public class InetAddressTest extends junit.framework.TestCase { } public void test_hashCode() throws Exception { - InetAddress addr1 = InetAddress.getByName("1.1"); - InetAddress addr2 = InetAddress.getByName("1.1.1"); - assertFalse(addr1.hashCode() == addr2.hashCode()); - - addr2 = InetAddress.getByName("1.0.0.1"); + InetAddress addr1 = InetAddress.getByName("1.0.0.1"); + InetAddress addr2 = InetAddress.getByName("1.0.0.1"); assertTrue(addr1.hashCode() == addr2.hashCode()); assertTrue(loopback6().hashCode() == localhost6().hashCode()); @@ -167,17 +209,15 @@ public class InetAddressTest extends junit.framework.TestCase { public void test_toString() throws Exception { String validIPAddresses[] = { - "::1.2.3.4", "::", "::", "1::0", "1::", - "::1", "0", /* jdk1.5 accepts 0 as valid */ + "::1.2.3.4", "::", "::", "1::0", "1::", "::1", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255", "0:0:0:0:0:0:0:0", "0:0:0:0:0:0:0.0.0.0" }; String [] resultStrings = { - "/::1.2.3.4", "/::", "/::", "/1::", "/1::", - "/::1", - "/0.0.0.0", "/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + "/::1.2.3.4", "/::", "/::", "/1::", "/1::", "/::1", + "/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "/::", "/::" }; |