http-client-branch: fix header field-value validation http-client-branch
authordfuchs
Thu, 29 Mar 2018 09:55:50 +0100
branchhttp-client-branch
changeset 56365 7b2e4c363335
parent 56355 bf89fba643d9
child 56366 d50e3549506e
http-client-branch: fix header field-value validation
src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
test/jdk/java/net/httpclient/HeadersTest.java
test/jdk/java/net/httpclient/HeadersTest1.java
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	Mon Mar 26 19:54:18 2018 +0100
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	Thu Mar 29 09:55:50 2018 +0100
@@ -379,29 +379,18 @@
      * is not permitted!
      */
     public static boolean isValidValue(String token) {
-        boolean accepted = true;
         for (int i = 0; i < token.length(); i++) {
             char c = token.charAt(i);
             if (c > 255) {
                 return false;
             }
-            if (accepted) {
-                if (c == ' ' || c == '\t') {
-                    accepted = false;
-                } else if (!fieldvchar[c]) {
-                    return false; // forbidden byte
-                }
-            } else {
-                if (c != ' ' && c != '\t') {
-                    if (fieldvchar[c]) {
-                        accepted = true;
-                    } else {
-                        return false; // forbidden byte
-                    }
-                }
+            if (c == ' ' || c == '\t') {
+                continue;
+            } else if (!fieldvchar[c]) {
+                return false; // forbidden byte
             }
         }
-        return accepted;
+        return true;
     }
 
 
--- a/test/jdk/java/net/httpclient/HeadersTest.java	Mon Mar 26 19:54:18 2018 +0100
+++ b/test/jdk/java/net/httpclient/HeadersTest.java	Thu Mar 29 09:55:50 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -324,6 +324,15 @@
         }
     }
 
+    static void goodValue(String value) {
+        HttpRequest.Builder builder = HttpRequest.newBuilder(TEST_URI);
+        try {
+            builder.header("x-good", value);
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException("Unexpected IAE for x-good: " + value);
+        }
+    }
+
     static void badURI() throws Exception {
         HttpRequest.Builder builder = HttpRequest.newBuilder();
         URI uri = URI.create(TEST_URI.toString().replace("http", "ftp"));
@@ -538,6 +547,9 @@
         good("Hello#world");
         good("Qwer#ert");
         badValue("blah\r\n blah");
+        goodValue("blah blah");
+        goodValue("blah  blah");
+        goodValue("\"blah\\\"  \\\"blah\"");
         nullName();
         nullValue();
         nullHeaders();
--- a/test/jdk/java/net/httpclient/HeadersTest1.java	Mon Mar 26 19:54:18 2018 +0100
+++ b/test/jdk/java/net/httpclient/HeadersTest1.java	Thu Mar 29 09:55:50 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -59,6 +59,7 @@
 public class HeadersTest1 {
 
     private static final String RESPONSE = "Hello world";
+    private static final String QUOTED = "a=\"quote\", b=\"\\\"quote\\\"  \\\"quote\\\"  codec\"";
 
     @Test
     public void test() throws Exception {
@@ -81,6 +82,7 @@
             HttpRequest req = HttpRequest.newBuilder(uri)
                                          .headers("X-Bar", "foo1")
                                          .headers("X-Bar", "foo2")
+                                         .headers("X-Quote",QUOTED)
                                          .GET()
                                          .build();
 
@@ -125,6 +127,10 @@
             assertTrue(multiline.get(0).contains(" foo=\"bar\""));
             assertTrue(multiline.get(0).contains(" bar=\"foo\""));
             assertTrue(multiline.get(0).contains(" foobar=\"barfoo\""));
+
+            // quote
+            List<String> quote = hd.allValues("X-Quote-Response");
+            assertEquals(quote, List.of(QUOTED));
         } finally {
             server.stop(0);
             e.shutdownNow();
@@ -145,12 +151,20 @@
                 he.close();
                 return;
             }
+            l = he.getRequestHeaders().get("X-Quote");
+            if (l.isEmpty() || l.size() != 1 || !QUOTED.equals(l.get(0))) {
+                System.out.println("Bad X-Quote: " + l);
+                he.sendResponseHeaders(500, -1);
+                he.close();
+                return;
+            }
             Headers h = he.getResponseHeaders();
             h.add("X-Foo-Response", "resp1");
             h.add("X-Foo-Response", "resp2");
             h.add("X-multi-line-response", "Custom foo=\"bar\","
                     + "\r\n    bar=\"foo\","
                     + "\r\n    foobar=\"barfoo\"");
+            h.add("X-Quote-Response", he.getRequestHeaders().getFirst("X-Quote"));
             he.sendResponseHeaders(200, RESPONSE.length());
             OutputStream os = he.getResponseBody();
             os.write(RESPONSE.getBytes(US_ASCII));