This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new 5374303735 Review "Fix archive index pre-check for mounted archive
resource sets"
5374303735 is described below
commit 53743037355bd69d6593e60139400882e6450bd4
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Oct 30 12:27:19 2026 +0000
Review "Fix archive index pre-check for mounted archive resource sets"
Correctly handled JAR resources with a non-empty internal path
---
.../webresources/AbstractArchiveResourceSet.java | 4 +--
.../apache/catalina/webresources/JarContents.java | 9 ++----
.../catalina/webresources/JarResourceRoot.java | 28 ++++++++++++++++-
.../catalina/webresources/TestJarContents.java | 36 ++++++++++------------
.../TestJarResourceSetInternalMount.java | 9 ++++++
.../webresources/TestJarWarResourceSet.java | 6 ++--
6 files changed, 61 insertions(+), 31 deletions(-)
diff --git
a/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
b/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
index c43479f4ea..35573acf58 100644
--- a/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
+++ b/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
@@ -280,7 +280,7 @@ public abstract class AbstractArchiveResourceSet extends
AbstractResourceSet {
if (!path.endsWith("/")) {
path = path + "/";
}
- return new JarResourceRoot(root, new File(getBase()),
baseUrlString, path);
+ return new JarResourceRoot(root, new File(getBase()),
baseUrlString, path, getInternalPath());
}
String pathInJar = getInternalPath() + pathSuffix;
@@ -296,7 +296,7 @@ public abstract class AbstractArchiveResourceSet extends
AbstractResourceSet {
* embedded in it) would result in false negatives.
*/
JarContents contents = jarContents;
- if (contents != null && !contents.mightContainResource(pathInJar,
"")) {
+ if (contents != null && !contents.mightContainResource(pathInJar))
{
return new EmptyResource(root, path);
}
diff --git a/java/org/apache/catalina/webresources/JarContents.java
b/java/org/apache/catalina/webresources/JarContents.java
index e6ab5093c0..abb13c93b0 100644
--- a/java/org/apache/catalina/webresources/JarContents.java
+++ b/java/org/apache/catalina/webresources/JarContents.java
@@ -159,16 +159,13 @@ public final class JarContents {
/**
* Method that identifies whether a given path <b>MIGHT</b> be in this
jar. Uses the Bloom filter mechanism.
*
- * @param path Requested path, including any internal path of the
resource set.
- * @param webappRoot The web application mount point of the resource set,
which can be stripped from the path.
+ * @param path Requested path, including any internal path of the resource
set but excluding the web application
+ * mount.
*
* @return Whether the prefix of the path is known to be in this jar.
*/
- public boolean mightContainResource(String path, String webappRoot) {
+ public boolean mightContainResource(String path) {
int startPos = 0;
- if (path.startsWith(webappRoot)) {
- startPos = webappRoot.length();
- }
while (startPos < path.length() && path.charAt(startPos) == '/') {
startPos++;
}
diff --git a/java/org/apache/catalina/webresources/JarResourceRoot.java
b/java/org/apache/catalina/webresources/JarResourceRoot.java
index 74d78476c4..f18a8483d9 100644
--- a/java/org/apache/catalina/webresources/JarResourceRoot.java
+++ b/java/org/apache/catalina/webresources/JarResourceRoot.java
@@ -22,10 +22,12 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.util.jar.Manifest;
import org.apache.catalina.WebResourceRoot;
+import org.apache.catalina.util.URLEncoder;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -38,6 +40,7 @@ public class JarResourceRoot extends AbstractResource {
private final File base;
private final String baseUrl;
+ private final String internalPath;
private final String name;
/**
@@ -47,8 +50,25 @@ public class JarResourceRoot extends AbstractResource {
* @param base the base file
* @param baseUrl the base URL
* @param webAppPath the web application path
+ *
+ * @deprecated Unused. Will be removed in Tomcat 12
*/
+ @Deprecated
public JarResourceRoot(WebResourceRoot root, File base, String baseUrl,
String webAppPath) {
+ this(root, base, baseUrl, webAppPath, "");
+ }
+
+ /**
+ * Constructs a new JarResourceRoot.
+ *
+ * @param root the resource root
+ * @param base the base file
+ * @param baseUrl the base URL
+ * @param webAppPath the web application path
+ * @param internalPath the internal path that has been mounted
+ */
+ public JarResourceRoot(WebResourceRoot root, File base, String baseUrl,
String webAppPath,
+ String internalPath) {
super(root, webAppPath);
// Validate the webAppPath before going any further
if (!webAppPath.endsWith("/")) {
@@ -56,6 +76,7 @@ public class JarResourceRoot extends AbstractResource {
}
this.base = base;
this.baseUrl = "jar:" + baseUrl;
+ this.internalPath = internalPath;
// Extract the name from the webAppPath
// Strip the trailing '/' character
String resourceName = webAppPath.substring(0, webAppPath.length() - 1);
@@ -133,7 +154,12 @@ public class JarResourceRoot extends AbstractResource {
@Override
public URL getURL() {
- String url = baseUrl + "!/";
+ String url;
+ if (internalPath.isEmpty()) {
+ url = baseUrl + "!/";
+ } else {
+ url = baseUrl + "!" + URLEncoder.DEFAULT.encode(internalPath,
StandardCharsets.UTF_8) + "/";
+ }
try {
return new URI(url).toURL();
} catch (MalformedURLException | URISyntaxException |
IllegalArgumentException e) {
diff --git a/test/org/apache/catalina/webresources/TestJarContents.java
b/test/org/apache/catalina/webresources/TestJarContents.java
index 5fd2a9e618..f2b6314ec3 100644
--- a/test/org/apache/catalina/webresources/TestJarContents.java
+++ b/test/org/apache/catalina/webresources/TestJarContents.java
@@ -65,42 +65,40 @@ public class TestJarContents {
@Test
public void testMightContainResource() {
- Assert.assertTrue(testJarContentsObject.mightContainResource(
- "/d1/d1-f1.txt", jar.getAbsolutePath()));
+
Assert.assertTrue(testJarContentsObject.mightContainResource("/d1/d1-f1.txt"));
Assert.assertTrue(testJarContentsObject.mightContainResource(
- "d1/d1-f1.txt", jar.getAbsolutePath()));
+ "d1/d1-f1.txt"));
Assert.assertTrue(testJarContentsObject.mightContainResource(
- "f9.txt", jar.getAbsolutePath()));
+ "f9.txt"));
Assert.assertFalse(testJarContentsObject.mightContainResource(
- "/d7/d1-f1.txt", jar.getAbsolutePath()));
+ "/d7/d1-f1.txt"));
// A path that only contains slashes (once the webapp root and any
// leading slashes have been removed) refers to the root of the
// archive. That cannot be ruled out, so the method must return
// true.
Assert.assertTrue(testJarContentsObject.mightContainResource(
- "/", jar.getAbsolutePath()));
+ "/"));
Assert.assertTrue(testJarContentsObject.mightContainResource(
- "/////", jar.getAbsolutePath()));
+ "/////"));
- Assert.assertTrue(testJarContentsObject.mightContainResource(
- jar.getAbsolutePath(), jar.getAbsolutePath()));
+ Assert.assertTrue(testJarContentsObject.mightContainResource(""));
}
@Test
public void testEmptyPath() {
// Must not throw and must return true since nothing can be ruled
// out.
- Assert.assertTrue(testJarContentsObject.mightContainResource("",
jar.getAbsolutePath()));
+ Assert.assertTrue(testJarContentsObject.mightContainResource(""));
}
@Test(expected = NullPointerException.class)
public void testNullPointerExceptions() {
- testJarContentsObject.mightContainResource(null,
jar.getAbsolutePath());
+ testJarContentsObject.mightContainResource(null);
}
@Test
@@ -147,20 +145,20 @@ public class TestJarContents {
try (JarFile jarFile = new JarFile(f)) {
JarContents jarContents = new JarContents(jarFile);
- Assert.assertTrue(jarContents.mightContainResource("real.txt",
""));
+ Assert.assertTrue(jarContents.mightContainResource("real.txt"));
Assert.assertTrue(
-
jarContents.mightContainResource("META-INF/versions/9x/foo.txt", ""));
+
jarContents.mightContainResource("META-INF/versions/9x/foo.txt"));
Assert.assertTrue(
-
jarContents.mightContainResource("META-INF/versions//bar.txt", ""));
+
jarContents.mightContainResource("META-INF/versions//bar.txt"));
Assert.assertTrue(jarContents.mightContainResource(
- "META-INF/versions/99999999999999/ovf.txt", ""));
+ "META-INF/versions/99999999999999/ovf.txt"));
// A leading slash is not significant
Assert.assertTrue(
-
jarContents.mightContainResource("/META-INF/versions/9x/lead.txt", ""));
+
jarContents.mightContainResource("/META-INF/versions/9x/lead.txt"));
// Signed and valid version segments record the base name
- Assert.assertTrue(jarContents.mightContainResource("plus.txt",
""));
- Assert.assertTrue(jarContents.mightContainResource("minus.txt",
""));
- Assert.assertTrue(jarContents.mightContainResource("ok.txt", ""));
+ Assert.assertTrue(jarContents.mightContainResource("plus.txt"));
+ Assert.assertTrue(jarContents.mightContainResource("minus.txt"));
+ Assert.assertTrue(jarContents.mightContainResource("ok.txt"));
}
}
}
diff --git
a/test/org/apache/catalina/webresources/TestJarResourceSetInternalMount.java
b/test/org/apache/catalina/webresources/TestJarResourceSetInternalMount.java
index 2d890b5fdc..6f8a35ddd1 100644
--- a/test/org/apache/catalina/webresources/TestJarResourceSetInternalMount.java
+++ b/test/org/apache/catalina/webresources/TestJarResourceSetInternalMount.java
@@ -62,6 +62,15 @@ public class TestJarResourceSetInternalMount extends
AbstractTestResourceSetMoun
return "test-file-12";
}
+ @Test
+ public void testGetResourceRootUrl() {
+ WebResource mountRoot = resourceRoot.getResource(getMount());
+
+ Assert.assertEquals(
+ "jar:" + new
File("test/webresources/dir1-internal.jar").toURI() + "!/dir1/",
+ mountRoot.getURL().toString());
+ }
+
@Test
public void testGetResourceAfterBloomFilterBuilt() {
// Regression test: resources must still be found once the archive
diff --git a/test/org/apache/catalina/webresources/TestJarWarResourceSet.java
b/test/org/apache/catalina/webresources/TestJarWarResourceSet.java
index 89dee0828c..a93ad83fa0 100644
--- a/test/org/apache/catalina/webresources/TestJarWarResourceSet.java
+++ b/test/org/apache/catalina/webresources/TestJarWarResourceSet.java
@@ -122,9 +122,9 @@ public class TestJarWarResourceSet extends TomcatBaseTest {
// The bloom filter is built from the resulting index
JarContents jarContents = resourceSet.jarContents;
Assert.assertNotNull(jarContents);
-
Assert.assertTrue(jarContents.mightContainResource("META-INF/versions/9x/foo.txt",
""));
- Assert.assertTrue(jarContents.mightContainResource("ok.txt", ""));
- Assert.assertTrue(jarContents.mightContainResource("real.txt", ""));
+
Assert.assertTrue(jarContents.mightContainResource("META-INF/versions/9x/foo.txt"));
+ Assert.assertTrue(jarContents.mightContainResource("ok.txt"));
+ Assert.assertTrue(jarContents.mightContainResource("real.txt"));
// The index and the bloom filter have to agree on the name an entry is
// stored under, otherwise these lookups would be rejected by the
filter
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]