File tomcat-9.0.36-CVE-2025-49125.patch of Package tomcat.40071

From 9418e3ff9f1f4c006b4661311ae9376c52d162b9 Mon Sep 17 00:00:00 2001
From: Mark Thomas <markt@apache.org>
Date: Wed, 4 Jun 2025 11:28:24 +0100
Subject: [PATCH] Expand checks for webAppMount

---
Index: apache-tomcat-9.0.36-src/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
===================================================================
--- apache-tomcat-9.0.36-src.orig/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
+++ apache-tomcat-9.0.36-src/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java
@@ -68,7 +68,7 @@ public abstract class AbstractArchiveRes
         String webAppMount = getWebAppMount();
 
         ArrayList<String> result = new ArrayList<>();
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             String pathInJar =
                     getInternalPath() + path.substring(webAppMount.length());
             // Always strip off the leading '/' to get the JAR path
@@ -118,7 +118,7 @@ public abstract class AbstractArchiveRes
         String webAppMount = getWebAppMount();
 
         ResourceSet<String> result = new ResourceSet<>();
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             String pathInJar =
                     getInternalPath() + path.substring(webAppMount.length());
             // Always strip off the leading '/' to get the JAR path and make
@@ -229,7 +229,7 @@ public abstract class AbstractArchiveRes
         // If the JAR has been mounted below the web application root, return
         // an empty resource for requests outside of the mount point.
 
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             String pathInJar = getInternalPath() + path.substring(
                     webAppMount.length(), path.length());
             // Always strip off the leading '/' to get the JAR path
Index: apache-tomcat-9.0.36-src/java/org/apache/catalina/webresources/AbstractResourceSet.java
===================================================================
--- apache-tomcat-9.0.36-src.orig/java/org/apache/catalina/webresources/AbstractResourceSet.java
+++ apache-tomcat-9.0.36-src/java/org/apache/catalina/webresources/AbstractResourceSet.java
@@ -85,6 +85,18 @@ public abstract class AbstractResourceSe
         return webAppMount;
     }
 
+    protected boolean isPathMounted(String path, String webAppMount) {
+        // Doesn't call getWebAppMount() as value might have changed
+        if (path.startsWith(webAppMount)) {
+            if (path.length() != webAppMount.length() && path.charAt(webAppMount.length()) != '/') {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+
     public final void setBase(String base) {
         this.base = base;
     }
Index: apache-tomcat-9.0.36-src/test/org/apache/catalina/webresources/AbstractTestResourceSet.java
===================================================================
--- apache-tomcat-9.0.36-src.orig/test/org/apache/catalina/webresources/AbstractTestResourceSet.java
+++ apache-tomcat-9.0.36-src/test/org/apache/catalina/webresources/AbstractTestResourceSet.java
@@ -97,7 +97,7 @@ public abstract class AbstractTestResour
     }
 
     @Test
-    public final void testGetResourceDirA() {
+    public final void testGetResourceDirWithoutTrailingFileSeperator() {
         WebResource webResource = resourceRoot.getResource(getMount() + "/d1");
         Assert.assertTrue(webResource.isDirectory());
         Assert.assertEquals("d1", webResource.getName());
@@ -108,7 +108,7 @@ public abstract class AbstractTestResour
     }
 
     @Test
-    public final void testGetResourceDirB() {
+    public final void testGetResourceDirWithTrailingFileSeperator() {
         WebResource webResource = resourceRoot.getResource(getMount() + "/d1/");
         Assert.assertTrue(webResource.isDirectory());
         Assert.assertEquals("d1", webResource.getName());
@@ -119,6 +119,18 @@ public abstract class AbstractTestResour
     }
 
     @Test
+    public final void testGetResourceDirWithoutLeadingFileSeperator() {
+        String mount = getMount();
+        if (mount.isEmpty()) {
+            // Test is only meaningful when resource is mounted below web application root.
+            return;
+        }
+        WebResource webResource = resourceRoot.getResource(mount + "d1");
+        Assert.assertFalse(webResource.exists());
+        Assert.assertEquals(mount + "d1", webResource.getWebappPath());
+    }
+
+    @Test
     public final void testGetResourceFile() {
         WebResource webResource =
                 resourceRoot.getResource(getMount() + "/d1/d1-f1.txt");
Index: apache-tomcat-9.0.36-src/webapps/docs/changelog.xml
===================================================================
--- apache-tomcat-9.0.36-src.orig/webapps/docs/changelog.xml
+++ apache-tomcat-9.0.36-src/webapps/docs/changelog.xml
@@ -143,6 +143,10 @@
         Refactor GCI servlet to access resources via the
         <code>WebResource</code> API. (markt)
       </scode>
+      <fix>
+        Expand the path checks for Pre-Resources and Post-Resources mounted at a
+        path within the web application. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">
Index: apache-tomcat-9.0.36-src/java/org/apache/catalina/webresources/DirResourceSet.java
===================================================================
--- apache-tomcat-9.0.36-src.orig/java/org/apache/catalina/webresources/DirResourceSet.java
+++ apache-tomcat-9.0.36-src/java/org/apache/catalina/webresources/DirResourceSet.java
@@ -109,7 +109,7 @@ public class DirResourceSet extends Abst
         checkPath(path);
         String webAppMount = getWebAppMount();
         WebResourceRoot root = getRoot();
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             /*
              * Lock the path for reading until the WebResource has been constructed. The lock prevents concurrent reads
              * and writes (e.g. HTTP GET and PUT / DELETE) for the same path causing corruption of the FileResource
@@ -141,7 +141,7 @@ public class DirResourceSet extends Abst
     public String[] list(String path) {
         checkPath(path);
         String webAppMount = getWebAppMount();
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             File f = file(path.substring(webAppMount.length()), true);
             if (f == null) {
                 return EMPTY_STRING_ARRAY;
@@ -174,7 +174,7 @@ public class DirResourceSet extends Abst
         checkPath(path);
         String webAppMount = getWebAppMount();
         ResourceSet<String> result = new ResourceSet<>();
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             File f = file(path.substring(webAppMount.length()), true);
             if (f != null) {
                 File[] list = f.listFiles();
@@ -216,7 +216,7 @@ public class DirResourceSet extends Abst
             return false;
         }
         String webAppMount = getWebAppMount();
-        if (path.startsWith(webAppMount)) {
+        if (isPathMounted(path, webAppMount)) {
             File f = file(path.substring(webAppMount.length()), false);
             if (f == null) {
                 return false;
@@ -247,7 +247,7 @@ public class DirResourceSet extends Abst
         }
 
         String webAppMount = getWebAppMount();
-        if (!path.startsWith(webAppMount)) {
+        if (!isPathMounted(path, webAppMount)) {
             return false;
         }
 
openSUSE Build Service is sponsored by