diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_77.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_77.mod new file mode 100644 index 00000000000..3628757cbfd --- /dev/null +++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_77.mod @@ -0,0 +1,8 @@ +[name] +protonego-boot + +[files] +http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar + +[exec] +-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.7.v20160121.jar diff --git a/jetty-start/src/test/resources/dist-home/modules/protonego-impl/alpn-1.8.0_77.mod b/jetty-start/src/test/resources/dist-home/modules/protonego-impl/alpn-1.8.0_77.mod new file mode 100644 index 00000000000..3628757cbfd --- /dev/null +++ b/jetty-start/src/test/resources/dist-home/modules/protonego-impl/alpn-1.8.0_77.mod @@ -0,0 +1,8 @@ +[name] +protonego-boot + +[files] +http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.7.v20160121/alpn-boot-8.1.7.v20160121.jar|lib/alpn/alpn-boot-8.1.7.v20160121.jar + +[exec] +-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.7.v20160121.jar diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java index ca070dd8c14..03d2a180fb7 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java @@ -381,6 +381,53 @@ public class StringUtil } } + /** + * Find the index of a control characters in String + *

+ * This will return a result on the first occurrence of a control character, regardless if + * there are more than one. + *

+ *

+ * Note: uses codepoint version of {@link Character#isISOControl(int)} to support Unicode better. + *

+ * + *
+     *   indexOfControlChars(null)      == -1
+     *   indexOfControlChars("")        == -1
+     *   indexOfControlChars("\r\n")    == 0
+     *   indexOfControlChars("\t")      == 0
+     *   indexOfControlChars("   ")     == -1
+     *   indexOfControlChars("a")       == -1
+     *   indexOfControlChars(".")       == -1
+     *   indexOfControlChars(";\n")     == 1
+     *   indexOfControlChars("abc\f")   == 3
+     *   indexOfControlChars("z\010")   == 1
+     *   indexOfControlChars(":\u001c") == 1
+     * 
+ * + * @param str + * the string to test. + * @return the index of first control character in string, -1 if no control characters encountered + */ + public static int indexOfControlChars(String str) + { + if (str == null) + { + return -1; + } + int len = str.length(); + for (int i = 0; i < len; i++) + { + if (Character.isISOControl(str.codePointAt(i))) + { + // found a control character, we can stop searching now + return i; + } + } + // no control characters + return -1; + } + /* ------------------------------------------------------------ */ /** * Test if a string is null or only has whitespace characters in it. diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/FileResource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/FileResource.java index b5c7bacf3c5..d4942eec15e 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/FileResource.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/FileResource.java @@ -29,10 +29,12 @@ import java.net.URL; import java.net.URLConnection; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; +import java.nio.file.InvalidPathException; import java.nio.file.StandardOpenOption; import java.security.Permission; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -67,6 +69,7 @@ public class FileResource extends Resource { // Try standard API to convert URL to file. file =new File(url.toURI()); + assertValidPath(file.toString()); } catch (URISyntaxException e) { @@ -110,6 +113,7 @@ public class FileResource extends Resource _file=file; URI file_uri=_file.toURI(); _uri=normalizeURI(_file,uri); + assertValidPath(file.toString()); // Is it a URI alias? if (!URIUtil.equalsIgnoreEncodings(_uri,file_uri.toString())) @@ -121,6 +125,7 @@ public class FileResource extends Resource /* -------------------------------------------------------- */ public FileResource(File file) { + assertValidPath(file.toString()); _file=file; _uri=normalizeURI(_file,_file.toURI()); _alias=checkFileAlias(_file); @@ -182,6 +187,7 @@ public class FileResource extends Resource public Resource addPath(String path) throws IOException, MalformedURLException { + assertValidPath(path); path = org.eclipse.jetty.util.URIUtil.canonicalPath(path); if (path==null) @@ -207,7 +213,7 @@ public class FileResource extends Resource } catch (final URISyntaxException e) { - throw new MalformedURLException(e.getMessage()) + throw new InvalidPathException(path, e.getMessage()) { { initCause(e); @@ -217,8 +223,16 @@ public class FileResource extends Resource return new FileResource(uri); } - - + + private void assertValidPath(String path) + { + int idx = StringUtil.indexOfControlChars(path); + if (idx >= 0) + { + throw new InvalidPathException(path, "Invalid Character at index " + idx); + } + } + /* ------------------------------------------------------------ */ @Override public URI getAlias() diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java index 7044923fcb5..892e34140c7 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -165,6 +166,7 @@ public class PathResource extends Resource public PathResource(Path path) { this.path = path.toAbsolutePath(); + assertValidPath(path); this.uri = this.path.toUri(); this.alias = checkAliasPath(path); } @@ -255,6 +257,17 @@ public class PathResource extends Resource return new PathResource(this.path.getFileSystem().getPath(path.toString(), subpath)); } + private void assertValidPath(Path path) + { + // TODO merged from 9.2, check if necessary + String str = path.toString(); + int idx = StringUtil.indexOfControlChars(str); + if(idx >= 0) + { + throw new InvalidPathException(str, "Invalid Character at index " + idx); + } + } + @Override public void close() { diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java index a33170a629c..09889fa891b 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java @@ -18,20 +18,20 @@ package org.eclipse.jetty.util; +import java.nio.charset.StandardCharsets; + +import org.junit.Assert; +import org.junit.Test; + import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.emptyArray; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import java.nio.charset.StandardCharsets; - -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; - public class StringUtilTest { @Test @@ -205,6 +205,25 @@ public class StringUtilTest System.err.println(calc); } + @Test + public void testHasControlCharacter() + { + assertThat(StringUtil.indexOfControlChars("\r\n"), is(0)); + assertThat(StringUtil.indexOfControlChars("\t"), is(0)); + assertThat(StringUtil.indexOfControlChars(";\n"), is(1)); + assertThat(StringUtil.indexOfControlChars("abc\fz"), is(3)); + assertThat(StringUtil.indexOfControlChars("z\010"), is(1)); + assertThat(StringUtil.indexOfControlChars(":\u001c"), is(1)); + + assertThat(StringUtil.indexOfControlChars(null), is(-1)); + assertThat(StringUtil.indexOfControlChars(""), is(-1)); + assertThat(StringUtil.indexOfControlChars(" "), is(-1)); + assertThat(StringUtil.indexOfControlChars("a"), is(-1)); + assertThat(StringUtil.indexOfControlChars("."), is(-1)); + assertThat(StringUtil.indexOfControlChars(";"), is(-1)); + assertThat(StringUtil.indexOfControlChars("Euro is \u20ac"), is(-1)); + } + @Test public void testIsBlank() {