This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit bc066cf7fce9ad783ca4c5a22b483abfbc55022a
Author: opencode <[email protected]>
AuthorDate: Thu Oct 8 17:09:48 2026 +0200

    Normalise a context path missing its leading slash in ContextName.
    
    The ContextName(String path, String version) constructor documented that a
    non-empty path must start with "/" but did not check it. The base name is
    derived with path.substring(1), so a path such as "foo" silently lost its
    first character and produced the base name "oo". This reached Tomcat's
    addWebapp(String, URL): the WAR was copied to appBase/oo.war while the
    context was later deployed as "/foo" (Context.setPath() prepends the missing
    slash), and the file name no longer corresponded to the deployed context.
    
    Prepend the missing leading slash for paths that lack it, mirroring the
    normalisation Context.setPath() performs. Well-formed inputs are unaffected,
    so valid callers (which already pass normalized context paths) produce
    identical results. A test covering the malformed input is added.
---
 java/org/apache/catalina/util/ContextName.java     | 10 ++++++++--
 test/org/apache/catalina/util/TestContextName.java | 13 +++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/util/ContextName.java 
b/java/org/apache/catalina/util/ContextName.java
index 01cf3805c7..cd871b9a43 100644
--- a/java/org/apache/catalina/util/ContextName.java
+++ b/java/org/apache/catalina/util/ContextName.java
@@ -102,15 +102,21 @@ public final class ContextName {
      *
      * @param path    Context path to use, which must not contain a version 
marker. May be <code>null</code>,
      *                 <code>""</code>, <code>"/"</code> or 
<code>"/ROOT"</code> to represent the root context. Any
-     *                 other value must start with <code>"/"</code>
+     *                 other value must start with <code>"/"</code>; if it 
does not, a leading <code>"/"</code> is
+     *                 prepended, matching the normalisation performed by
+     *                 {@link org.apache.catalina.Context#setPath(String)}.
      * @param version Context version to use
      */
     public ContextName(String path, String version) {
         // Path should never be null, '/' or '/ROOT'
         if (path == null || "/".equals(path) || "/ROOT".equals(path)) {
             this.path = "";
-        } else {
+        } else if (path.startsWith("/") || path.isEmpty()) {
             this.path = path;
+        } else {
+            // Normalise a malformed path the same way Context.setPath() does 
by adding the missing
+            // leading slash, so that the conversions below derive the 
expected name and base name
+            this.path = '/' + path;
         }
 
         // Version should never be null
diff --git a/test/org/apache/catalina/util/TestContextName.java 
b/test/org/apache/catalina/util/TestContextName.java
index ff8d62e81c..fa6d85cf6f 100644
--- a/test/org/apache/catalina/util/TestContextName.java
+++ b/test/org/apache/catalina/util/TestContextName.java
@@ -202,6 +202,19 @@ public class TestContextName {
         Assert.assertEquals("/foo", cn22.getDisplayName());
     }
 
+    @Test
+    public void testPathNormalisation() {
+        ContextName malformed = new ContextName("foo", null);
+        Assert.assertEquals("/foo", malformed.getPath());
+        Assert.assertEquals("/foo", malformed.getName());
+        Assert.assertEquals("foo", malformed.getBaseName());
+
+        ContextName malformedVersion = new ContextName("foo", "A");
+        Assert.assertEquals("/foo", malformedVersion.getPath());
+        Assert.assertEquals("/foo##A", malformedVersion.getName());
+        Assert.assertEquals("foo##A", malformedVersion.getBaseName());
+    }
+
     @Test
     public void testConstructorString() {
         doTestConstructorString(cn1);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to