This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit ac5fb31bd93efb13a704197a9b5ce06467decd7b 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 1552147dea..0b0983a660 100644 --- a/java/org/apache/catalina/util/ContextName.java +++ b/java/org/apache/catalina/util/ContextName.java @@ -101,15 +101,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]
