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]

Reply via email to