I have a scenario where my appBase looks something like this - /xyz/tomcat/webapps and I have a ROOT.war file and a pre-exploded war both as symlinks, something like - /xyz/tomcat/webapps/ROOT -> /abc/ROOT/ /xyz/tomcat/webapps/ROOT.war -> /abc/ROOT.war This means that in ContextConfig.fixDocBase():578, I see docBase = ROOT.war This then expands to docBase = /xyz/tomcat/webapps/ROOT.war at line:591. Stepping forward, at line:609, docBaseInAppBase gets set to true as my docBase indeed starts with the appBase string. Considering that the docBase value as of now ends in .war and it is not a directory and I have unpackWARS set to true, at line 614, docBase is set to '/xyz/tomcat/webapps/ROOT' (as that's what ExpandWars.expand returns). And then at line 616, docBase is set to the canonicalPath of /xyz/tomcat/webapps/ROOT which in my case is /abc/ROOT/ Note that my docBaseInAppBase is still set to true, which is now incorrect. This means that at line:656, either docBase.substring() throws an exception if my docBase was shorter than appBase, or, if not, context.setDocBase gets set to an invalid truncated value of the canonical path at line:665 which causes problems down the line. Specifically for longer canonical paths of the exploded war I get - Caused by: java.lang.IllegalArgumentException: The main resource set specified [<invalid-truncated-path>] is not valid 239 at org.apache.catalina.webresources.StandardRoot.createMainResourceSet(StandardRoot.java:729) ~[catalina.jar:8.5.4] 240 at org.apache.catalina.webresources.StandardRoot.startInternal(StandardRoot.java:686) ~[catalina.jar:8.5.4] 241 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152) ~[catalina.jar:8.5.4] 242 at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4831) ~[catalina.jar:8.5.4] 243 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4963) ~[catalina.jar:8.5.4] 244 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152) ~[catalina.jar:8.5.4] In my tests, refreshing the docBaseInAppBase value by calling again - docBaseInAppBase = docBase.startsWith(appBase.getPath() + File.separatorChar); just before line:655 (which checks the docBaseInAppBase value) solves the problem, but I'm not sure if I'm missing any other edge conditions. I'll really appreciate a formal fix for the issue. Thanks!
To summarize, ContextConfig.fixDocBase() is not correctly revalidating the fact that it thought docBase was inside appBase after it sets docBase to its canonical path.
This has been fixed in the following branches: - 9.0.x for 9.0.0.M10 onwards - 8.5.x for 8.5.5 onwards - 8.0.x for 8.0.37 onwards 7.0.x and earlier are not affected.