8233141: DatagramSocket.send doesn't specify exception thrown when no target address
Summary: DatagramSocket and MulticastSocket send methods are changed to throw IllegalArgumentException if no target address can be determined.
Reviewed-by: alanb
--- a/src/java.base/share/classes/java/net/DatagramSocket.java Mon Nov 18 17:11:06 2019 +0100
+++ b/src/java.base/share/classes/java/net/DatagramSocket.java Mon Nov 18 16:48:05 2019 +0000
@@ -646,7 +646,9 @@
* if this socket has an associated channel,
* and the channel is in non-blocking mode.
* @throws IllegalArgumentException if the socket is connected,
- * and connected address and packet address differ.
+ * and connected address and packet address differ, or
+ * if the socket is not connected and the packet address
+ * is not set.
*
* @see java.net.DatagramPacket
* @see SecurityManager#checkMulticast(InetAddress)
@@ -655,12 +657,15 @@
* @spec JSR-51
*/
public void send(DatagramPacket p) throws IOException {
- InetAddress packetAddress = null;
synchronized (p) {
if (isClosed())
throw new SocketException("Socket is closed");
- checkAddress (p.getAddress(), "send");
+ InetAddress packetAddress = p.getAddress();
+ checkAddress (packetAddress, "send");
if (connectState == ST_NOT_CONNECTED) {
+ if (packetAddress == null) {
+ throw new IllegalArgumentException("Address not set");
+ }
// check the address is ok with the security manager on every send.
SecurityManager security = System.getSecurityManager();
@@ -669,16 +674,15 @@
// while you are trying to send the packet for example
// after the security check but before the send.
if (security != null) {
- if (p.getAddress().isMulticastAddress()) {
- security.checkMulticast(p.getAddress());
+ if (packetAddress.isMulticastAddress()) {
+ security.checkMulticast(packetAddress);
} else {
- security.checkConnect(p.getAddress().getHostAddress(),
+ security.checkConnect(packetAddress.getHostAddress(),
p.getPort());
}
}
} else {
// we're connected
- packetAddress = p.getAddress();
if (packetAddress == null) {
p.setAddress(connectedAddress);
p.setPort(connectedPort);
--- a/src/java.base/share/classes/java/net/MulticastSocket.java Mon Nov 18 17:11:06 2019 +0100
+++ b/src/java.base/share/classes/java/net/MulticastSocket.java Mon Nov 18 16:48:05 2019 +0000
@@ -29,6 +29,7 @@
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;
+import java.net.PortUnreachableException;
/**
* The multicast datagram socket class is useful for sending
@@ -643,11 +644,19 @@
* @param ttl optional time to live for multicast packet.
* default ttl is 1.
*
- * @throws IOException is raised if an error occurs i.e
- * error while setting ttl.
+ * @throws IOException is raised if an error occurs i.e
+ * error while setting ttl.
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} or {@code checkConnect}
* method doesn't allow the send.
+ * @throws PortUnreachableException may be thrown if the socket is connected
+ * to a currently unreachable destination. Note, there is no
+ * guarantee that the exception will be thrown.
+ * @throws IllegalArgumentException if the socket is connected,
+ * and connected address and packet address differ, or
+ * if the socket is not connected and the packet address
+ * is not set.
+ *
*
* @deprecated Use the following code or its equivalent instead:
* ......
@@ -667,32 +676,34 @@
throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
- checkAddress(p.getAddress(), "send");
synchronized(ttlLock) {
synchronized(p) {
+ InetAddress packetAddress = p.getAddress();
+ checkAddress(packetAddress, "send");
if (connectState == ST_NOT_CONNECTED) {
+ if (packetAddress == null) {
+ throw new IllegalArgumentException("Address not set");
+ }
// Security manager makes sure that the multicast address
// is allowed one and that the ttl used is less
// than the allowed maxttl.
SecurityManager security = System.getSecurityManager();
if (security != null) {
- if (p.getAddress().isMulticastAddress()) {
- security.checkMulticast(p.getAddress(), ttl);
+ if (packetAddress.isMulticastAddress()) {
+ security.checkMulticast(packetAddress, ttl);
} else {
- security.checkConnect(p.getAddress().getHostAddress(),
+ security.checkConnect(packetAddress.getHostAddress(),
p.getPort());
}
}
} else {
// we're connected
- InetAddress packetAddress = null;
- packetAddress = p.getAddress();
if (packetAddress == null) {
p.setAddress(connectedAddress);
p.setPort(connectedPort);
} else if ((!packetAddress.equals(connectedAddress)) ||
p.getPort() != connectedPort) {
- throw new SecurityException("connected address and packet address" +
+ throw new IllegalArgumentException("connected address and packet address" +
" differ");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/DatagramSocket/AddressNotSet.java Mon Nov 18 16:48:05 2019 +0000
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8233141
+ * @summary DatagramSocket.send should throw IllegalArgumentException
+ * when the packet address is not correctly set.
+ * @run main AddressNotSet
+ */
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.SocketAddress;
+import java.nio.channels.DatagramChannel;
+
+import static java.lang.System.out;
+
+public class AddressNotSet {
+
+ final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
+ final DatagramSocket serversock;
+ int i;
+ AddressNotSet() throws Exception {
+ serversock = new DatagramSocket(0, loopbackAddress);
+ }
+
+ public static void main (String args[]) throws Exception {
+ new AddressNotSet().run();
+ }
+
+ public void run() throws Exception {
+ try (var ss = serversock) {
+ try (DatagramSocket sock = new DatagramSocket()) {
+ test(sock);
+ }
+ try (DatagramSocket sock = new MulticastSocket()) {
+ test(sock);
+ }
+ try (DatagramSocket sock = DatagramChannel.open().socket()) {
+ test(sock);
+ }
+ }
+ }
+
+ private void test(DatagramSocket sock) throws Exception {
+ out.println("Testing with " + sock.getClass());
+ InetAddress addr = loopbackAddress;
+ byte[] buf;
+ DatagramPacket p;
+ int port = serversock.getLocalPort();
+ SocketAddress connectedAddress = serversock.getLocalSocketAddress();
+
+ out.println("Checking send to non-connected address ...");
+ try {
+ out.println("Checking send with no packet address");
+ buf = ("Hello, server"+(++i)).getBytes();
+ p = new DatagramPacket(buf, buf.length);
+ sock.send(p);
+ throw new AssertionError("Expected IllegalArgumentException not received");
+ } catch (IllegalArgumentException x) {
+ out.println("Got expected exception: " + x);
+ }
+
+ out.println("Checking send to valid address");
+ buf = ("Hello, server"+(++i)).getBytes();
+ p = new DatagramPacket(buf, buf.length, addr, port);
+ sock.send(p);
+ serversock.receive(p);
+
+ out.println("Connecting to server address: " + connectedAddress);
+ sock.connect(connectedAddress);
+
+ try {
+ out.println("Checking send with different address than connected");
+ buf = ("Hello, server"+(++i)).getBytes();
+ p = new DatagramPacket(buf, buf.length, addr, port+1);
+ sock.send(p);
+ throw new AssertionError("Expected IllegalArgumentException not received");
+ } catch (IllegalArgumentException x) {
+ out.println("Got expected exception: " + x);
+ }
+
+ out.println("Checking send to valid address");
+ buf = ("Hello, server"+(++i)).getBytes();
+ p = new DatagramPacket(buf, buf.length, addr, port);
+ sock.send(p);
+ serversock.receive(p);
+
+ if (sock instanceof MulticastSocket) {
+ sock.disconnect();
+ testTTL((MulticastSocket)sock);
+ }
+ }
+
+ private void testTTL(MulticastSocket sock) throws Exception {
+ out.println("Testing deprecated send TTL with " + sock.getClass());
+ final byte ttl = 100;
+ InetAddress addr = loopbackAddress;
+ byte[] buf;
+ DatagramPacket p;
+ int port = serversock.getLocalPort();
+
+ out.println("Checking send to non-connected address ...");
+ try {
+ out.println("Checking send with no packet address");
+ buf = ("Hello, server"+(++i)).getBytes();
+ p = new DatagramPacket(buf, buf.length);
+ sock.send(p,ttl);
+ throw new AssertionError("Expected IllegalArgumentException not received");
+ } catch (IllegalArgumentException x) {
+ out.println("Got expected exception: " + x);
+ }
+
+ out.println("Connecting to connected address: " + sock);
+ sock.connect(addr, port);
+
+ try {
+ out.println("Checking send with different address than connected");
+ buf = ("Hello, server"+(++i)).getBytes();
+ p = new DatagramPacket(buf, buf.length, addr, port+1);
+ sock.send(p, ttl);
+ throw new AssertionError("Expected IllegalArgumentException not received");
+ } catch (IllegalArgumentException x) {
+ out.println("Got expected exception: " + x);
+ }
+ }
+}
--- a/test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java Mon Nov 18 17:11:06 2019 +0100
+++ b/test/jdk/java/net/DatagramSocket/SendDatagramToBadAddress.java Mon Nov 18 16:48:05 2019 +0000
@@ -110,12 +110,17 @@
}
public void run() throws Exception {
-
if (OSsupportsFeature()) {
print ("running on OS that supports ICMP port unreachable");
}
+ try (DatagramSocket sock = new DatagramSocket()) {
+ test(sock);
+ }
+ }
+
+ private void test(DatagramSocket sock) throws Exception {
+ print("Testing with " + sock.getClass());
InetAddress addr = InetAddress.getLoopbackAddress();
- DatagramSocket sock = new DatagramSocket();
DatagramSocket serversock = new DatagramSocket(0);
DatagramPacket p;
byte[] buf;