summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2011-06-03 12:43:17 -0700
committerElliott Hughes <enh@google.com>2011-06-03 23:27:56 -0700
commitfc041ff241f9a7556e72236f130de0215ecd17db (patch)
tree0f7bd89644f72779e4a23a21ef4d14432f711635 /luni
parent8f1bbe0b6549136be386d75edf70ed4daf8a25b0 (diff)
downloadlibcore-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.java42
-rw-r--r--luni/src/main/java/libcore/io/ForwardingOs.java2
-rw-r--r--luni/src/main/java/libcore/io/Os.java2
-rw-r--r--luni/src/main/java/libcore/io/Posix.java2
-rw-r--r--luni/src/main/native/libcore_io_Posix.cpp11
-rw-r--r--luni/src/test/java/libcore/java/net/InetAddressTest.java126
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", "/::",
"/::"
};