This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit f8e5b677120b754ecb556192c6a04b92ba7c92eb 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]
