changeset 57767:6bee0a3d2a3a

8230310: SocksSocketImpl should handle the IllegalArgumentException thrown by ProxySelector.select usage Summary: Catch the IAE thrown by ProxySelector.select and wrap it into a IOException Reviewed-by: dfuchs
author jpai
date Wed, 28 Aug 2019 20:05:43 +0530
parents ed7eb20871c5
children ef15850629cd
files src/java.base/share/classes/java/net/SocksSocketImpl.java test/jdk/java/net/Socks/SocksSocketImplTest.java
diffstat 2 files changed, 118 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/net/SocksSocketImpl.java	Fri Aug 30 12:24:16 2019 +0200
+++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java	Wed Aug 28 20:05:43 2019 +0530
@@ -29,6 +29,7 @@
 import java.io.OutputStream;
 import java.io.BufferedOutputStream;
 import java.security.AccessController;
+import java.util.Iterator;
 
 import jdk.internal.util.StaticProperty;
 import sun.net.SocksProxy;
@@ -327,8 +328,12 @@
             }
             Proxy p = null;
             IOException savedExc = null;
-            java.util.Iterator<Proxy> iProxy = null;
-            iProxy = sel.select(uri).iterator();
+            final Iterator<Proxy> iProxy;
+            try {
+                iProxy = sel.select(uri).iterator();
+            } catch (IllegalArgumentException iae) {
+                throw new IOException("Failed to select a proxy", iae);
+            }
             if (iProxy == null || !(iProxy.hasNext())) {
                 delegate.connect(epoint, remainingMillis(deadlineMillis));
                 return;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socks/SocksSocketImplTest.java	Wed Aug 28 20:05:43 2019 +0530
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import sun.net.spi.DefaultProxySelector;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+/**
+ * @test
+ * @bug 8230310
+ * @summary Tests java.net.SocksSocketImpl
+ * @run testng SocksSocketImplTest
+ * @modules java.base/sun.net.spi:+open
+ */
+public class SocksSocketImplTest {
+
+    private ProxySelector previousDefault;
+
+    @BeforeTest
+    public void beforeTest() {
+        previousDefault = ProxySelector.getDefault();
+        ProxySelector.setDefault(new SchemeStrippedProxySelector());
+    }
+
+    @AfterTest
+    public void afterTest() {
+        ProxySelector.setDefault(previousDefault);
+    }
+
+    /**
+     * Creates a socket connection, which internally triggers proxy selection for the target
+     * address. The test has been configured to use a {@link SchemeStrippedProxySelector ProxySelector}
+     * which throws a {@link IllegalArgumentException}. This test then verifies that this IAE gets wrapped
+     * by {@code java.net.SocksSocketImpl} into an {@link IOException} before being thrown
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testIOEOnProxySelection() throws Exception {
+        final int backlog = -1;
+        final int port = 0;
+        try (ServerSocket ss = new ServerSocket(port, backlog, InetAddress.getLoopbackAddress());
+             Socket s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
+             Socket s2 = ss.accept()) {
+            Assert.fail("IOException was expected to be thrown, but wasn't");
+        } catch (IOException ioe) {
+            // expected
+            // now verify the IOE was thrown for the correct expected reason
+            if (!(ioe.getCause() instanceof IllegalArgumentException)) {
+                // rethrow this so that the test output failure will capture the entire/real
+                // cause in its stacktrace
+                throw ioe;
+            }
+        }
+    }
+
+    /**
+     * A {@link ProxySelector} which strips the "scheme" part of the {@link URI}
+     * before delegating the selection to the the {@link DefaultProxySelector}.
+     * This is to ensure that the {@code DefaultProxySelector} throws an {@link IllegalArgumentException}
+     * during selection of the proxy
+     */
+    private static final class SchemeStrippedProxySelector extends DefaultProxySelector {
+
+        @Override
+        public List<Proxy> select(final URI uri) {
+            System.out.println("Proxy selection for " + uri);
+            final URI schemeStrippedURI;
+            try {
+                // strip the scheme and pass the rest
+                schemeStrippedURI = new URI(null, uri.getHost(), uri.getPath(), null);
+            } catch (URISyntaxException e) {
+                throw new RuntimeException(e);
+            }
+            System.out.println("Scheme stripped URI " + schemeStrippedURI + " is being used to select a proxy");
+            return super.select(schemeStrippedURI);
+        }
+    }
+}