diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java index 52b5e1487c..2130ba1395 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java @@ -255,6 +255,10 @@ final class JarURLConnection extends java.net.JarURLConnection { static JarURLConnection get(URL url, JarFile jarFile) throws IOException { StringSequence spec = new StringSequence(url.getFile()); int index = indexOfRootSpec(spec, jarFile.getPathFromRoot()); + if (index == -1) { + return (Boolean.TRUE.equals(useFastExceptions.get()) ? NOT_FOUND_CONNECTION + : new JarURLConnection(url, null, EMPTY_JAR_ENTRY_NAME)); + } int separator; while ((separator = spec.indexOf(SEPARATOR, index)) > 0) { JarEntryName entryName = JarEntryName.get(spec.subSequence(index, separator)); @@ -275,7 +279,7 @@ final class JarURLConnection extends java.net.JarURLConnection { private static int indexOfRootSpec(StringSequence file, String pathFromRoot) { int separatorIndex = file.indexOf(SEPARATOR); - if (separatorIndex < 0) { + if (separatorIndex < 0 || !file.startsWith(pathFromRoot, separatorIndex)) { return -1; } return separatorIndex + SEPARATOR.length() + pathFromRoot.length(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/StringSequence.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/StringSequence.java index a1989f6083..c298cf6886 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/StringSequence.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/StringSequence.java @@ -95,6 +95,17 @@ final class StringSequence implements CharSequence { return this.source.indexOf(str, this.start + fromIndex) - this.start; } + public boolean startsWith(CharSequence prefix) { + return startsWith(prefix, 0); + } + + public boolean startsWith(CharSequence prefix, int toffset) { + if (length() - prefix.length() - toffset < 0) { + return false; + } + return subSequence(toffset, toffset + prefix.length()).equals(prefix); + } + @Override public String toString() { return this.source.substring(this.start, this.end); @@ -117,10 +128,10 @@ final class StringSequence implements CharSequence { if (this == obj) { return true; } - if (obj == null || getClass() != obj.getClass()) { + if (obj == null || !CharSequence.class.isInstance(obj)) { return false; } - StringSequence other = (StringSequence) obj; + CharSequence other = (CharSequence) obj; int n = length(); if (n == other.length()) { int i = 0; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java index 58f655f547..38ae048837 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java @@ -18,6 +18,7 @@ package org.springframework.boot.loader.jar; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileNotFoundException; import java.net.URL; import org.junit.Before; @@ -149,6 +150,16 @@ public class JarURLConnectionTests { .hasSameContentAs(new ByteArrayInputStream(new byte[] { 3 })); } + @Test + public void connectionToEntryUsingWrongAbsoluteUrlForEntryFromNestedJarFile() + throws Exception { + URL url = new URL("jar:file:" + getAbsolutePath() + "!/w.jar!/3.dat"); + JarFile nested = this.jarFile + .getNestedJarFile(this.jarFile.getEntry("nested.jar")); + this.thrown.expect(FileNotFoundException.class); + JarURLConnection.get(url, nested).getInputStream(); + } + @Test public void getContentLengthReturnsLengthOfUnderlyingEntry() throws Exception { URL url = new URL(new URL("jar", null, -1, diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/StringSequenceTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/StringSequenceTests.java index 5d43e94f6e..d9d2d48ece 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/StringSequenceTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/StringSequenceTests.java @@ -167,4 +167,46 @@ public class StringSequenceTests { assertThat(a).isEqualTo(b).isNotEqualTo(c); } + @Test + public void startsWithWhenExactMatch() { + assertThat(new StringSequence("abc").startsWith("abc")).isTrue(); + } + + @Test + public void startsWithWhenLongerAndStartsWith() { + assertThat(new StringSequence("abcd").startsWith("abc")).isTrue(); + } + + @Test + public void startsWithWhenLongerAndDoesNotStartWith() { + assertThat(new StringSequence("abcd").startsWith("abx")).isFalse(); + } + + @Test + public void startsWithWhenShorterAndDoesNotStartWith() { + assertThat(new StringSequence("ab").startsWith("abc")).isFalse(); + assertThat(new StringSequence("ab").startsWith("c")).isFalse(); + } + + @Test + public void startsWithOffsetWhenExactMatch() { + assertThat(new StringSequence("xabc").startsWith("abc", 1)).isTrue(); + } + + @Test + public void startsWithOffsetWhenLongerAndStartsWith() { + assertThat(new StringSequence("xabcd").startsWith("abc", 1)).isTrue(); + } + + @Test + public void startsWithOffsetWhenLongerAndDoesNotStartWith() { + assertThat(new StringSequence("xabcd").startsWith("abx", 1)).isFalse(); + } + + @Test + public void startsWithOffsetWhenShorterAndDoesNotStartWith() { + assertThat(new StringSequence("xab").startsWith("abc", 1)).isFalse(); + assertThat(new StringSequence("xab").startsWith("c", 1)).isFalse(); + } + }