Merge changes I1d36c13e,Ia8d00990
* changes:
Don't crash when passing null destinations to bind, connect, and sendto
Add tests for passing null to bind, sendto and connect.
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index 635619a..4072b6b 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -987,7 +987,8 @@
static void Linux_bindSocketAddress(
JNIEnv* env, jobject thisObj, jobject javaFd, jobject javaSocketAddress) {
- if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
+ if (javaSocketAddress != NULL &&
+ env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
// Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
jobject javaInetAddress;
jint port;
@@ -1169,7 +1170,8 @@
static void Linux_connectSocketAddress(
JNIEnv* env, jobject thisObj, jobject javaFd, jobject javaSocketAddress) {
- if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
+ if (javaSocketAddress != NULL &&
+ env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
// Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
jobject javaInetAddress;
jint port;
@@ -2187,7 +2189,8 @@
}
static jint Linux_sendtoBytesSocketAddress(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaSocketAddress) {
- if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
+ if (javaSocketAddress != NULL &&
+ env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
// Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
jobject javaInetAddress;
jint port;
@@ -2203,11 +2206,19 @@
sockaddr_storage ss;
socklen_t sa_len;
- if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
- return -1;
+ const sockaddr* sa;
+
+ if (javaSocketAddress != NULL) {
+ if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
+ return -1;
+ }
+
+ sa = reinterpret_cast<const sockaddr*>(&ss);
+ } else {
+ sa = NULL;
+ sa_len = 0;
}
- const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
// We don't need the return value because we'll already have thrown.
return NET_FAILURE_RETRY(env, ssize_t, sendto, javaFd, bytes.get() + byteOffset, byteCount, flags, sa, sa_len);
}
diff --git a/luni/src/test/java/libcore/libcore/io/OsTest.java b/luni/src/test/java/libcore/libcore/io/OsTest.java
index 91105bf..557b640 100644
--- a/luni/src/test/java/libcore/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/OsTest.java
@@ -309,13 +309,67 @@
Libcore.os.close(clientFd);
}
+ interface ExceptionalRunnable {
+ public void run() throws Exception;
+ }
+
+ /**
+ * Expects that the given Runnable will throw an exception of the specified class. If the class is
+ * ErrnoException, and expectedErrno is non-null, also checks that the errno is equal to
+ * expectedErrno.
+ */
+ private static void expectException(ExceptionalRunnable r, Class<? extends Exception> exClass,
+ Integer expectedErrno, String msg) {
+ try {
+ r.run();
+ fail(msg + " did not throw exception");
+ } catch (Exception e) {
+ assertEquals(msg + " threw unexpected exception", exClass, e.getClass());
+
+ if (expectedErrno != null) {
+ if (e instanceof ErrnoException) {
+ assertEquals(msg + "threw ErrnoException with unexpected error number",
+ (int) expectedErrno, ((ErrnoException) e).errno);
+ } else {
+ fail("Can only pass expectedErrno when expecting ErrnoException");
+ }
+ }
+
+ }
+ }
+
+ private static void expectBindException(FileDescriptor socket, SocketAddress addr,
+ Class exClass, Integer expectedErrno) {
+ String msg = String.format("bind(%s, %s)", socket, addr);
+ expectException(() -> { Libcore.os.bind(socket, addr); }, exClass, expectedErrno, msg);
+ }
+
+ private static void expectConnectException(FileDescriptor socket, SocketAddress addr,
+ Class exClass, Integer expectedErrno) {
+ String msg = String.format("connect(%s, %s)", socket, addr);
+ expectException(() -> { Libcore.os.connect(socket, addr); }, exClass, expectedErrno, msg);
+ }
+
+ private static void expectSendtoException(FileDescriptor socket, SocketAddress addr,
+ Class exClass, Integer expectedErrno) {
+ String msg = String.format("sendto(%s, %s)", socket, addr);
+ byte[] packet = new byte[42];
+ expectException(() -> { Libcore.os.sendto(socket, packet, 0, packet.length, 0, addr); },
+ exClass, expectedErrno, msg);
+ }
+
private static void expectBindConnectSendtoSuccess(FileDescriptor socket, String socketDesc,
SocketAddress addr) {
String msg = socketDesc + " socket to " + addr.toString();
try {
- // Expect bind to succeed.
try {
+ // Expect that bind throws when any of its arguments are null.
+ expectBindException(null, addr, ErrnoException.class, EBADF);
+ expectBindException(socket, null, NullPointerException.class, null);
+ expectBindException(null, null, NullPointerException.class, null);
+
+ // Expect bind to succeed.
Libcore.os.bind(socket, addr);
// Find out which port we're actually bound to, and use that in subsequent connect() and
@@ -330,13 +384,26 @@
addr = socknameISA;
}
+ // Expect sendto with a null address to throw because the socket is not connected, but to
+ // succeed with a non-null address.
+ byte[] packet = new byte[42];
+ Libcore.os.sendto(socket, packet, 0, packet.length, 0, addr);
+ // UNIX and IP sockets return different errors for this operation, so we can't check errno.
+ expectSendtoException(socket, null, ErrnoException.class, null);
+ expectSendtoException(null, null, ErrnoException.class, EBADF);
+
+ // Expect that connect throws when any of its arguments are null.
+ expectConnectException(null, addr, ErrnoException.class, EBADF);
+ expectConnectException(socket, null, NullPointerException.class, null);
+ expectConnectException(null, null, NullPointerException.class, null);
+
// Expect connect to succeed.
Libcore.os.connect(socket, addr);
assertEquals(Libcore.os.getsockname(socket), Libcore.os.getpeername(socket));
- // Expect sendto to succeed.
- byte[] packet = new byte[42];
+ // Expect sendto to succeed both when given an explicit address and a null address.
Libcore.os.sendto(socket, packet, 0, packet.length, 0, addr);
+ Libcore.os.sendto(socket, packet, 0, packet.length, 0, null);
} catch (SocketException | ErrnoException e) {
fail("Expected success for " + msg + ", but got: " + e);
}