Index: apache-tomcat-8.0.53-src/java/org/apache/catalina/servlets/DefaultServlet.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/catalina/servlets/DefaultServlet.java
+++ apache-tomcat-8.0.53-src/java/org/apache/catalina/servlets/DefaultServlet.java
@@ -1704,7 +1704,7 @@ public class DefaultServlet extends Http
// First check that the resulting path is under the provided base
try {
- if (!candidate.getCanonicalPath().startsWith(base.getCanonicalPath())) {
+ if (!candidate.getCanonicalFile().toPath().startsWith(base.getCanonicalFile().toPath())) {
return null;
}
} catch (IOException ioe) {
Index: apache-tomcat-8.0.53-src/java/org/apache/catalina/session/FileStore.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/catalina/session/FileStore.java
+++ apache-tomcat-8.0.53-src/java/org/apache/catalina/session/FileStore.java
@@ -352,7 +352,7 @@ public final class FileStore extends Sto
File file = new File(storageDir, filename);
// Check the file is within the storage directory
- if (!file.getCanonicalPath().startsWith(storageDir.getCanonicalPath())) {
+ if (!file.getCanonicalFile().toPath().startsWith(storageDir.getCanonicalFile().toPath())) {
log.warn(sm.getString("fileStore.invalid", file.getPath(), id));
return null;
}
Index: apache-tomcat-8.0.53-src/java/org/apache/catalina/startup/ContextConfig.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/catalina/startup/ContextConfig.java
+++ apache-tomcat-8.0.53-src/java/org/apache/catalina/startup/ContextConfig.java
@@ -571,29 +571,32 @@ public class ContextConfig implements Li
Host host = (Host) context.getParent();
File appBase = host.getAppBaseFile();
- String docBase = context.getDocBase();
- if (docBase == null) {
+ // This could be blank, relative, absolute or canonical
+ String docBaseConfigured = context.getDocBase();
+ // If there is no explicit docBase, derive it from the path and version
+ if (docBaseConfigured == null) {
// Trying to guess the docBase according to the path
String path = context.getPath();
if (path == null) {
return;
}
ContextName cn = new ContextName(path, context.getWebappVersion());
- docBase = cn.getBaseName();
+ docBaseConfigured = cn.getBaseName();
}
- File file = new File(docBase);
- if (!file.isAbsolute()) {
- docBase = (new File(appBase, docBase)).getPath();
+ // Obtain the absolute docBase in String and File form
+ String docBaseAbsolute;
+ File docBaseConfiguredFile = new File(docBaseConfigured);
+ if (!docBaseConfiguredFile.isAbsolute()) {
+ docBaseAbsolute = (new File(appBase, docBaseConfigured)).getAbsolutePath();
} else {
- docBase = file.getCanonicalPath();
+ docBaseAbsolute = docBaseConfiguredFile.getAbsolutePath();
}
- file = new File(docBase);
- String origDocBase = docBase;
+ File docBaseAbsoluteFile = new File(docBaseAbsolute);
+ String originalDocBase = docBaseAbsolute;
ContextName cn = new ContextName(context.getPath(), context.getWebappVersion());
String pathName = cn.getBaseName();
-
boolean unpackWARs = true;
if (host instanceof StandardHost) {
unpackWARs = ((StandardHost) host).isUnpackWARs();
@@ -602,28 +605,29 @@ public class ContextConfig implements Li
}
}
- boolean docBaseInAppBase = docBase.startsWith(appBase.getPath() + File.separatorChar);
-
- if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") && !file.isDirectory()) {
- URL war = UriUtil.buildJarUrl(new File(docBase));
+ // At this point we need to determine if we have a WAR file in the
+ // appBase that needs to be expanded. Therefore we consider the absolute
+ // docBase NOT the canonical docBase. This is because some users symlink
+ // WAR files into the appBase and we want this to work correctly.
+ boolean docBaseAbsoluteInAppBase = docBaseAbsolute.startsWith(appBase.getPath() + File.separatorChar);
+ if (docBaseAbsolute.toLowerCase(Locale.ENGLISH).endsWith(".war") && !docBaseAbsoluteFile.isDirectory()) {
+ URL war = UriUtil.buildJarUrl(docBaseAbsoluteFile);
if (unpackWARs) {
- docBase = ExpandWar.expand(host, war, pathName);
- file = new File(docBase);
- docBase = file.getCanonicalPath();
+ docBaseAbsolute = ExpandWar.expand(host, war, pathName);
+ docBaseAbsoluteFile = new File(docBaseAbsolute);
if (context instanceof StandardContext) {
- ((StandardContext) context).setOriginalDocBase(origDocBase);
+ ((StandardContext) context).setOriginalDocBase(originalDocBase);
}
} else {
ExpandWar.validate(host, war, pathName);
}
} else {
- File docDir = new File(docBase);
- File warFile = new File(docBase + ".war");
+ File docBaseAbsoluteFileWar = new File(docBaseAbsolute + ".war");
URL war = null;
- if (warFile.exists() && docBaseInAppBase) {
- war = UriUtil.buildJarUrl(warFile);
+ if (docBaseAbsoluteFileWar.exists() && docBaseAbsoluteInAppBase) {
+ war = UriUtil.buildJarUrl(docBaseAbsoluteFileWar);
}
- if (docDir.exists()) {
+ if (docBaseAbsoluteFile.exists()) {
if (war != null && unpackWARs) {
// Check if WAR needs to be re-expanded (e.g. if it has
// changed). Note: HostConfig.deployWar() takes care of
@@ -634,31 +638,33 @@ public class ContextConfig implements Li
} else {
if (war != null) {
if (unpackWARs) {
- docBase = ExpandWar.expand(host, war, pathName);
- file = new File(docBase);
- docBase = file.getCanonicalPath();
+ docBaseAbsolute = ExpandWar.expand(host, war, pathName);
+ docBaseAbsoluteFile = new File(docBaseAbsolute);
} else {
- docBase = warFile.getCanonicalPath();
+ docBaseAbsolute = docBaseAbsoluteFileWar.getAbsolutePath();
+ docBaseAbsoluteFile = docBaseAbsoluteFileWar;
ExpandWar.validate(host, war, pathName);
}
}
if (context instanceof StandardContext) {
- ((StandardContext) context).setOriginalDocBase(origDocBase);
+ ((StandardContext) context).setOriginalDocBase(originalDocBase);
}
}
}
- // Re-calculate now docBase is a canonical path
- docBaseInAppBase = docBase.startsWith(appBase.getPath() + File.separatorChar);
+ String docBaseCanonical = docBaseAbsoluteFile.getCanonicalPath();
- if (docBaseInAppBase) {
- docBase = docBase.substring(appBase.getPath().length());
+ // Re-calculate now docBase is a canonical path
+ boolean docBaseCanonicalInAppBase = docBaseAbsoluteFile.getCanonicalFile().toPath().startsWith(appBase.toPath());
+ String docBase;
+ if (docBaseCanonicalInAppBase) {
+ docBase = docBaseCanonical.substring(appBase.getPath().length());
docBase = docBase.replace(File.separatorChar, '/');
if (docBase.startsWith("/")) {
docBase = docBase.substring(1);
}
} else {
- docBase = docBase.replace(File.separatorChar, '/');
+ docBase = docBaseCanonical.replace(File.separatorChar, '/');
}
context.setDocBase(docBase);
Index: apache-tomcat-8.0.53-src/java/org/apache/catalina/startup/ExpandWar.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/catalina/startup/ExpandWar.java
+++ apache-tomcat-8.0.53-src/java/org/apache/catalina/startup/ExpandWar.java
@@ -26,6 +26,7 @@ import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
+import java.nio.file.Path;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -116,10 +117,7 @@ public class ExpandWar {
}
// Expand the WAR into the new document base directory
- String canonicalDocBasePrefix = docBase.getCanonicalPath();
- if (!canonicalDocBasePrefix.endsWith(File.separator)) {
- canonicalDocBasePrefix += File.separator;
- }
+ Path canonicalDocBasePath = docBase.getCanonicalFile().toPath();
// Creating war tracker parent (normally META-INF)
File warTrackerParent = warTracker.getParentFile();
@@ -134,14 +132,13 @@ public class ExpandWar {
JarEntry jarEntry = jarEntries.nextElement();
String name = jarEntry.getName();
File expandedFile = new File(docBase, name);
- if (!expandedFile.getCanonicalPath().startsWith(
- canonicalDocBasePrefix)) {
+ if (!expandedFile.getCanonicalFile().toPath().startsWith(canonicalDocBasePath)) {
// Trying to expand outside the docBase
// Throw an exception to stop the deployment
throw new IllegalArgumentException(
sm.getString("expandWar.illegalPath",war, name,
expandedFile.getCanonicalPath(),
- canonicalDocBasePrefix));
+ canonicalDocBasePath));
}
int last = name.lastIndexOf('/');
if (last >= 0) {
@@ -210,10 +207,7 @@ public class ExpandWar {
File docBase = new File(host.getAppBaseFile(), pathname);
// Calculate the document base directory
- String canonicalDocBasePrefix = docBase.getCanonicalPath();
- if (!canonicalDocBasePrefix.endsWith(File.separator)) {
- canonicalDocBasePrefix += File.separator;
- }
+ Path canonicalDocBasePath = docBase.getCanonicalFile().toPath();
JarURLConnection juc = (JarURLConnection) war.openConnection();
juc.setUseCaches(false);
try (JarFile jarFile = juc.getJarFile()) {
@@ -222,14 +216,13 @@ public class ExpandWar {
JarEntry jarEntry = jarEntries.nextElement();
String name = jarEntry.getName();
File expandedFile = new File(docBase, name);
- if (!expandedFile.getCanonicalPath().startsWith(
- canonicalDocBasePrefix)) {
+ if (!expandedFile.getCanonicalFile().toPath().startsWith(canonicalDocBasePath)) {
// Entry located outside the docBase
// Throw an exception to stop the deployment
throw new IllegalArgumentException(
sm.getString("expandWar.illegalPath",war, name,
expandedFile.getCanonicalPath(),
- canonicalDocBasePrefix));
+ canonicalDocBasePath));
}
}
} catch (IOException e) {
Index: apache-tomcat-8.0.53-src/java/org/apache/catalina/startup/HostConfig.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/catalina/startup/HostConfig.java
+++ apache-tomcat-8.0.53-src/java/org/apache/catalina/startup/HostConfig.java
@@ -598,8 +598,7 @@ public class HostConfig
docBase = new File(host.getAppBaseFile(), context.getDocBase());
}
// If external docBase, register .xml as redeploy first
- if (!docBase.getCanonicalPath().startsWith(
- host.getAppBaseFile().getAbsolutePath() + File.separator)) {
+ if (!docBase.getCanonicalFile().toPath().startsWith(host.getAppBaseFile().toPath())) {
isExternal = true;
deployedApp.redeployResources.put(
contextXml.getAbsolutePath(),
Index: apache-tomcat-8.0.53-src/webapps/docs/changelog.xml
===================================================================
--- apache-tomcat-8.0.53-src.orig/webapps/docs/changelog.xml
+++ apache-tomcat-8.0.53-src/webapps/docs/changelog.xml
@@ -141,6 +141,11 @@
Improve validation of storage location when using FileStore. (markt)
+
+ 63872: Fix some edge cases where the docBase was not being
+ set using a canonical path which in turn meant resource URLs were not
+ being constructed as expected. (markt)
+
@@ -280,6 +285,10 @@
Implement checksum checks when downloading dependencies that are used
to build Tomcat. (kkolinko)
+
+ Use java.nio.file.Path
to test for one directory being a
+ sub-directory of another in a consistent way. (markt)
+