8037396: URI getQuery() and getFragment() don't decode properly
Reviewed-by: chegar, michaelm
Contributed-by: pavel.reppo@oracle.com
--- a/jdk/src/share/classes/java/net/URI.java Mon Apr 07 13:16:17 2014 +0100
+++ b/jdk/src/share/classes/java/net/URI.java Mon Apr 07 15:40:05 2014 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, 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
@@ -1337,7 +1337,7 @@
*/
public String getQuery() {
if ((decodedQuery == null) && (query != null))
- decodedQuery = decode(query);
+ decodedQuery = decode(query, false);
return decodedQuery;
}
@@ -1366,7 +1366,7 @@
*/
public String getFragment() {
if ((decodedFragment == null) && (fragment != null))
- decodedFragment = decode(fragment);
+ decodedFragment = decode(fragment, false);
return decodedFragment;
}
@@ -2764,6 +2764,12 @@
// with a scope_id
//
private static String decode(String s) {
+ return decode(s, true);
+ }
+
+ // This method was introduced as a generalization of URI.decode method
+ // to provide a fix for JDK-8037396
+ private static String decode(String s, boolean ignorePercentInBrackets) {
if (s == null)
return s;
int n = s.length();
@@ -2776,8 +2782,8 @@
ByteBuffer bb = ByteBuffer.allocate(n);
CharBuffer cb = CharBuffer.allocate(n);
CharsetDecoder dec = ThreadLocalCoders.decoderFor("UTF-8")
- .onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
// This is not horribly efficient, but it will do for now
char c = s.charAt(0);
@@ -2790,7 +2796,7 @@
} else if (betweenBrackets && c == ']') {
betweenBrackets = false;
}
- if (c != '%' || betweenBrackets) {
+ if (c != '%' || (betweenBrackets && ignorePercentInBrackets)) {
sb.append(c);
if (++i >= n)
break;
--- a/jdk/test/java/net/URI/Test.java Mon Apr 07 13:16:17 2014 +0100
+++ b/jdk/test/java/net/URI/Test.java Mon Apr 07 15:40:05 2014 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, 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
@@ -1367,6 +1367,17 @@
cmp0(u, v, true);
}
+ static void eq(String expected, String actual) {
+ if (expected == null && actual == null) {
+ return;
+ }
+ if (expected != null && expected.equals(actual)) {
+ return;
+ }
+ throw new AssertionError(String.format(
+ "Strings are not equal: '%s', '%s'", expected, actual));
+ }
+
static void eqeq(URI u, URI v) {
testCount++;
if (u != v)
@@ -1588,7 +1599,12 @@
// miscellaneous bugs/rfes that don't fit in with the test framework
static void bugs() {
- // 6339649 - include detail message from nested exception
+ b6339649();
+ b8037396();
+ }
+
+ // 6339649 - include detail message from nested exception
+ private static void b6339649() {
try {
URI uri = URI.create("http://nowhere.net/should not be permitted");
} catch (IllegalArgumentException e) {
@@ -1598,6 +1614,39 @@
}
}
+ private static void b8037396() {
+
+ // primary checks:
+
+ URI u;
+ try {
+ u = new URI("http", "example.org", "/[a b]", "[a b]", "[a b]");
+ } catch (URISyntaxException e) {
+ throw new AssertionError("shouldn't ever happen", e);
+ }
+ eq("/[a b]", u.getPath());
+ eq("[a b]", u.getQuery());
+ eq("[a b]", u.getFragment());
+
+ // additional checks:
+ // * '%' symbols are still decoded outside square brackets
+ // * the getRawXXX() functionality left intact
+
+ try {
+ u = new URI("http", "example.org", "/a b[c d]", "a b[c d]", "a b[c d]");
+ } catch (URISyntaxException e) {
+ throw new AssertionError("shouldn't ever happen", e);
+ }
+
+ eq("/a b[c d]", u.getPath());
+ eq("a b[c d]", u.getQuery());
+ eq("a b[c d]", u.getFragment());
+
+ eq("/a%20b%5Bc%20d%5D", u.getRawPath());
+ eq("a%20b[c%20d]", u.getRawQuery());
+ eq("a%20b[c%20d]", u.getRawFragment());
+ }
+
public static void main(String[] args) throws Exception {
switch (args.length) {