# HG changeset patch
# User dfuchs
# Date 1520362510 0
# Node ID 4b2272dfe7209ceeb26f8e17403aa736fc1b36f5
# Parent 875dbf6234f2b7c957d62080401e563a50505f7a
http-client-branch: 8199135: Validate that method names are tokens
diff -r 875dbf6234f2 -r 4b2272dfe720 src/java.net.http/share/classes/java/net/http/HttpRequest.java
--- a/src/java.net.http/share/classes/java/net/http/HttpRequest.java Tue Mar 06 18:43:27 2018 +0000
+++ b/src/java.net.http/share/classes/java/net/http/HttpRequest.java Tue Mar 06 18:55:10 2018 +0000
@@ -272,7 +272,10 @@
* @param method the method to use
* @param bodyPublisher the body publisher
* @return this builder
- * @throws IllegalArgumentException if the method is restricted
+ * @throws IllegalArgumentException if the method name is not
+ * valid, see
+ * RFC 7230 section-3.1.1, or the method is restricted by the
+ * implementation.
*/
public Builder method(String method, BodyPublisher bodyPublisher);
diff -r 875dbf6234f2 -r 4b2272dfe720 src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestBuilderImpl.java
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestBuilderImpl.java Tue Mar 06 18:43:27 2018 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestBuilderImpl.java Tue Mar 06 18:55:10 2018 +0000
@@ -195,6 +195,12 @@
throw newIAE("illegal method ");
if (method.equals("CONNECT"))
throw newIAE("method CONNECT is not supported");
+ if (!Utils.isValidName(method))
+ throw newIAE("illegal method \""
+ + method.replace("\n","\\n")
+ .replace("\r", "\\r")
+ .replace("\t", "\\t")
+ + "\"");
return method0(method, requireNonNull(body));
}
diff -r 875dbf6234f2 -r 4b2272dfe720 src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java Tue Mar 06 18:43:27 2018 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java Tue Mar 06 18:55:10 2018 +0000
@@ -41,6 +41,7 @@
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.Utils;
import jdk.internal.net.http.websocket.WebSocketRequest;
import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
@@ -94,8 +95,14 @@
*/
public HttpRequestImpl(HttpRequest request, ProxySelector ps) {
String method = request.method();
+ if (method != null && !Utils.isValidName(method))
+ throw new IllegalArgumentException("illegal method \""
+ + method.replace("\n","\\n")
+ .replace("\r", "\\r")
+ .replace("\t", "\\t")
+ + "\"");
this.method = method == null ? "GET" : method;
- this.userHeaders = request.headers();
+ this.userHeaders = ImmutableHeaders.of(request.headers());
if (request instanceof HttpRequestImpl) {
// all cases exception WebSocket should have a new system headers
this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
@@ -145,6 +152,7 @@
private HttpRequestImpl(URI uri,
String method,
HttpRequestImpl other) {
+ assert method == null || Utils.isValidName(method);
this.method = method == null? "GET" : method;
this.userHeaders = other.userHeaders;
this.isWebSocket = other.isWebSocket;
diff -r 875dbf6234f2 -r 4b2272dfe720 test/jdk/java/net/httpclient/MethodsTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/MethodsTest.java Tue Mar 06 18:55:10 2018 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018, 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 jdk.internal.net.http.common.HttpHeadersImpl;
+
+import java.io.IOException;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.URI;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.Optional;
+
+/**
+ * @test
+ * @bug 8199135
+ * @modules java.net.http/jdk.internal.net.http.common
+ * @summary Basic test for method names
+ */
+public class MethodsTest {
+
+ static final URI TEST_URI = URI.create("http://www.foo.com/");
+ static final String FORBIDDEN = "()<>@,;:\\\"/[]?={} \t\r\n";
+
+ static void bad(String name) throws IOException, InterruptedException {
+ HttpRequest.Builder builder = HttpRequest.newBuilder(TEST_URI);
+ try {
+ builder.method(name, HttpRequest.BodyPublishers.noBody());
+ throw new RuntimeException("Expected IAE for method:" + name);
+ } catch (IllegalArgumentException expected) {
+ System.out.println("Got expected IAE: " + expected);
+ }
+ try {
+ HttpRequest req = new HttpRequest() {
+ @Override public Optional bodyPublisher() {
+ return Optional.of(BodyPublishers.noBody());
+ }
+ @Override public String method() {
+ return name;
+ }
+ @Override public Optional timeout() {
+ return Optional.empty();
+ }
+ @Override public boolean expectContinue() {
+ return false;
+ }
+ @Override public URI uri() {
+ return TEST_URI;
+ }
+ @Override public Optional version() {
+ return Optional.empty();
+ }
+ @Override public HttpHeaders headers() {
+ return new HttpHeadersImpl();
+ }
+ };
+ HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
+ throw new RuntimeException("Expected IAE for method:" + name);
+ } catch (IllegalArgumentException expected) {
+ System.out.println("Got expected IAE: " + expected);
+ }
+ }
+
+ static void good(String name) {
+ HttpRequest.Builder builder = HttpRequest.newBuilder(TEST_URI);
+ try {
+ builder.method(name, HttpRequest.BodyPublishers.noBody());
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Unexpected IAE for header:" + name);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ bad("bad:method");
+ bad("Foo\n");
+ good("X-Foo!");
+ good("Bar~");
+ good("x");
+ bad(" ");
+ bad("x y");
+ bad("x\t");
+ bad("Bar\r\n");
+ good("Hello#world");
+ good("Qwer#ert");
+ bad("m\u00e9thode");
+ for (char c =0; c < 256 ; c++) {
+ if (c < 32 || FORBIDDEN.indexOf(c) > -1 || c >= 127) {
+ bad("me" + c + "thod");
+ bad(c + "thod");
+ bad("me" + c);
+ } else {
+ good("me" + c + "thod");
+ good(c + "thod");
+ good("me" + c);
+ }
+ }
+ }
+}