You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2017/09/22 10:39:51 UTC

svn commit: r1809298 - /tomcat/tc7.0.x/trunk/java/org/apache/naming/resources/FileDirContext.java

Author: markt
Date: Fri Sep 22 10:39:51 2017
New Revision: 1809298

URL: http://svn.apache.org/viewvc?rev=1809298&view=rev
Log:
Code clean-up as a result of code reviews
- Minor performance optimisation
- Simplify code
- Additional commentary

Modified:
    tomcat/tc7.0.x/trunk/java/org/apache/naming/resources/FileDirContext.java

Modified: tomcat/tc7.0.x/trunk/java/org/apache/naming/resources/FileDirContext.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/naming/resources/FileDirContext.java?rev=1809298&r1=1809297&r2=1809298&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/naming/resources/FileDirContext.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/naming/resources/FileDirContext.java Fri Sep 22 10:39:51 2017
@@ -815,53 +815,69 @@ public class FileDirContext extends Base
         // If the requested names ends in '/', the Java File API will return a
         // matching file if one exists. This isn't what we want as it is not
         // consistent with the Servlet spec rules for request mapping.
-        if (file.isFile() && name.endsWith("/")) {
+        if (name.endsWith("/") && file.isFile()) {
             return null;
         }
 
-        if (!mustExist || file.exists() && file.canRead()) {
+        // If the file/dir must exist but the identified file/dir can't be read
+        // then signal that the resource was not found
+        if (mustExist && !file.canRead()) {
+            return null;
+        }
 
-            if (allowLinking)
-                return file;
+        // If allow linking is enabled, files are not limited to being located
+        // under the fileBase so all further checks are disabled.
+        if (allowLinking)
+            return file;
+
+        // Check that this file is located under the web application root
+        String canPath = null;
+        try {
+            canPath = file.getCanonicalPath();
+        } catch (IOException e) {
+            // Ignore
+        }
+        if (canPath == null || !canPath.startsWith(absoluteBase)) {
+            return null;
+        }
 
-            // Check that this file belongs to our root path
-            String canPath = null;
-            try {
-                canPath = file.getCanonicalPath();
-            } catch (IOException e) {
-                // Ignore
-            }
-            if (canPath == null)
-                return null;
-
-            // Check to see if going outside of the web application root
-            if (!canPath.startsWith(absoluteBase)) {
-                return null;
-            }
-
-            // Case sensitivity check - this is now always done
-            String fileAbsPath = file.getAbsolutePath();
-            if (fileAbsPath.endsWith("."))
-                fileAbsPath = fileAbsPath + "/";
-            String absPath = normalize(fileAbsPath);
-            canPath = normalize(canPath);
-            if ((absoluteBase.length() < absPath.length())
-                && (absoluteBase.length() < canPath.length())) {
-                absPath = absPath.substring(absoluteBase.length() + 1);
-                if (absPath.equals(""))
-                    absPath = "/";
-                canPath = canPath.substring(absoluteBase.length() + 1);
-                if (canPath.equals(""))
-                    canPath = "/";
-                if (!canPath.equals(absPath))
-                    return null;
-            }
+        // Ensure that the file is not outside the fileBase. This should not be
+        // possible for standard requests (the request is normalized early in
+        // the request processing) but might be possible for some access via the
+        // Servlet API (RequestDispatcher, HTTP/2 push etc.) therefore these
+        // checks are retained as an additional safety measure
+        // absoluteBase has been normalized so absPath needs to be normalized as
+        // well.
+        String absPath = normalize(file.getAbsolutePath());
+        if ((absoluteBase.length() > absPath.length())) {
+            return null;
+        }
 
-        } else {
+        // Remove the fileBase location from the start of the paths since that
+        // was not part of the requested path and the remaining check only
+        // applies to the request path
+        absPath = absPath.substring(absoluteBase.length());
+        canPath = canPath.substring(absoluteBase.length());
+
+        // Case sensitivity check
+        // The normalized requested path should be an exact match the equivalent
+        // canonical path. If it is not, possible reasons include:
+        // - case differences on case insensitive file systems
+        // - Windows removing a trailing ' ' or '.' from the file name
+        //
+        // In all cases, a mis-match here results in the resource not being
+        // found
+        //
+        // absPath is normalized so canPath needs to be normalized as well
+        // Can't normalize canPath earlier as canonicalBase is not normalized
+        if (canPath.length() > 0) {
+            canPath = normalize(canPath);
+        }
+        if (!canPath.equals(absPath)) {
             return null;
         }
-        return file;
 
+        return file;
     }
 
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org