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 dbbe95a7a3 Follow-up to "Normalise a context path missing its leading 
slash ..."
dbbe95a7a3 is described below

commit dbbe95a7a3f9ee8d9cf72a95737aa3e5c7e6b6c7
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Oct 19 21:19:06 2026 +0100

    Follow-up to "Normalise a context path missing its leading slash ..."
    
    Make path handling consistent.i
    - "ROOT" and "/ROOT" now map to the ROOT context.
    - trailing "/" characters are removed
---
 java/org/apache/catalina/core/StandardContext.java | 16 ++++++++-----
 java/org/apache/catalina/util/ContextName.java     | 26 ++++++++++++++--------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/java/org/apache/catalina/core/StandardContext.java 
b/java/org/apache/catalina/core/StandardContext.java
index 8f1bd4d8cc..8051d58a96 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -2146,8 +2146,16 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
 
     @Override
     public void setPath(String path) {
+        String original = path;
         boolean invalid = false;
-        if (path == null || path.equals("/")) {
+        if (path != null) {
+            while (path.endsWith("/")) {
+                invalid = true;
+                path = path.substring(0, path.length() - 1);
+            }
+        }
+
+        if (path == null || "/ROOT".equals(path) || "ROOT".equals(path)) {
             invalid = true;
             this.path = "";
         } else if (path.isEmpty() || path.startsWith("/")) {
@@ -2156,12 +2164,8 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
             invalid = true;
             this.path = "/" + path;
         }
-        if (this.path.endsWith("/")) {
-            invalid = true;
-            this.path = this.path.substring(0, this.path.length() - 1);
-        }
         if (invalid) {
-            log.warn(sm.getString("standardContext.pathInvalid", path, 
this.path));
+            log.warn(sm.getString("standardContext.pathInvalid", original, 
this.path));
         }
         encodedPath = URLEncoder.DEFAULT.encode(this.path, 
StandardCharsets.UTF_8);
         if (getName() == null) {
diff --git a/java/org/apache/catalina/util/ContextName.java 
b/java/org/apache/catalina/util/ContextName.java
index cd871b9a43..e31ca6ae3b 100644
--- a/java/org/apache/catalina/util/ContextName.java
+++ b/java/org/apache/catalina/util/ContextName.java
@@ -101,17 +101,24 @@ public final class ContextName {
      * Construct an instance from a path and version.
      *
      * @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>; if it 
does not, a leading <code>"/"</code> is
-     *                 prepended, matching the normalisation performed by
-     *                 {@link org.apache.catalina.Context#setPath(String)}.
+     *                 <code>""</code>, <code>"/"</code>, <code>"/ROOT"</code> 
or <code>"ROOT"</code> to represent the
+     *                 root context. Any 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)}. 
Trailing <code>"/"</code> characters are
+     *                 removed.
      * @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)) {
+        if (path != null) {
+            while (path.endsWith("/")) {
+                path = path.substring(0, path.length() - 1);
+            }
+        }
+
+        // Path should never be null, '/', '/ROOT' or 'ROOT'. Neither should 
they end with '/'.
+        if (path == null || "/ROOT".equals(path) || "ROOT".equals(path)) {
             this.path = "";
-        } else if (path.startsWith("/") || path.isEmpty()) {
+        } else if (path.isEmpty() || path.startsWith("/")) {
             this.path = path;
         } else {
             // Normalise a malformed path the same way Context.setPath() does 
by adding the missing
@@ -214,12 +221,13 @@ public final class ContextName {
     public boolean isPathValid() {
         // No need to test for null since path can never be null (see 
constructors)
         //
+        // No need to test for empty or start with / (see constructors)
+        //
         // Therefore, just need to check:
-        // - empty or start with /
         // - normalized and no attempt to escape the root
         //
         // Note: Normalize check on empty path would fail
-        return path.isEmpty() || (path.startsWith("/") && 
path.equals(RequestUtil.normalize(path)));
+        return path.isEmpty() || path.equals(RequestUtil.normalize(path));
     }
 
 


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

Reply via email to