Author: markt
Date: Fri Apr 27 17:14:19 2018
New Revision: 1830367

URL: http://svn.apache.org/viewvc?rev=1830367&view=rev
Log:
Collapse multiple leading '/' characters to a single '/' in the return value of 
HttpServletRequest#getContextPath() to avoid issues if the value is used with 
HttpServletResponse#sendRedirect(). This behaviour is enabled by default and 
configurable via the new Context attribute 
allowMultipleLeadingForwardSlashInPath.

Modified:
    tomcat/trunk/java/org/apache/catalina/Context.java
    tomcat/trunk/java/org/apache/catalina/connector/Request.java
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
    tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/context.xml

Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Fri Apr 27 17:14:19 2018
@@ -1843,4 +1843,24 @@ public interface Context extends Contain
      * @return The default response body encoding
      */
     public String getResponseCharacterEncoding();
+
+    /**
+     * Configure if, when returning a context path from {@link
+     * javax.servlet.http.HttpServletRequest#getContextPath()}, the return 
value
+     * is allowed to contain multiple leading '/' characters.
+     *
+     * @param allowMultipleLeadingForwardSlashInPath The new value for the flag
+     */
+    public void setAllowMultipleLeadingForwardSlashInPath(
+            boolean allowMultipleLeadingForwardSlashInPath);
+
+    /**
+     * When returning a context path from {@link
+     * javax.servlet.http.HttpServletRequest#getContextPath()}, is it allowed 
to
+     * contain multiple leading '/' characters?
+     *
+     * @return <code>true</code> if multiple leading '/' characters are 
allowed,
+     *         otherwise <code>false</code>
+     */
+    public boolean getAllowMultipleLeadingForwardSlashInPath();
 }

Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Fri Apr 27 
17:14:19 2018
@@ -2026,15 +2026,28 @@ public class Request implements HttpServ
      */
     @Override
     public String getContextPath() {
-        String canonicalContextPath = getServletContext().getContextPath();
-        String uri = getRequestURI();
-        char[] uriChars = uri.toCharArray();
         int lastSlash = mappingData.contextSlashCount;
         // Special case handling for the root context
         if (lastSlash == 0) {
             return "";
         }
+
+        String canonicalContextPath = getServletContext().getContextPath();
+
+        String uri = getRequestURI();
         int pos = 0;
+        if (!getContext().getAllowMultipleLeadingForwardSlashInPath()) {
+            // Ensure that the returned value only starts with a single '/'.
+            // This prevents the value being misinterpreted as a protocol-
+            // relative URI if used with sendRedirect().
+            do {
+                pos++;
+            } while (pos < uri.length() && uri.charAt(pos) == '/');
+            pos--;
+            uri = uri.substring(pos);
+        }
+
+        char[] uriChars = uri.toCharArray();
         // Need at least the number of slashes in the context path
         while (lastSlash > 0) {
             pos = nextSlash(uriChars, pos + 1);

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Fri Apr 27 
17:14:19 2018
@@ -806,9 +806,25 @@ public class StandardContext extends Con
 
     private String responseEncoding = null;
 
+    private boolean allowMultipleLeadingForwardSlashInPath = false;
+
+
     // ----------------------------------------------------- Context Properties
 
     @Override
+    public void setAllowMultipleLeadingForwardSlashInPath(
+            boolean allowMultipleLeadingForwardSlashInPath) {
+        this.allowMultipleLeadingForwardSlashInPath = 
allowMultipleLeadingForwardSlashInPath;
+    }
+
+
+    @Override
+    public boolean getAllowMultipleLeadingForwardSlashInPath() {
+        return allowMultipleLeadingForwardSlashInPath;
+    }
+
+
+    @Override
     public String getRequestCharacterEncoding() {
         return requestEncoding;
     }

Modified: tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java Fri Apr 27 
17:14:19 2018
@@ -801,4 +801,12 @@ public class FailedContext extends Lifec
     public void setResponseCharacterEncoding(String encoding) { /* NO-OP */ }
     @Override
     public String getResponseCharacterEncoding() { return null; }
+
+    @Override
+    public void setAllowMultipleLeadingForwardSlashInPath(
+            boolean allowMultipleLeadingForwardSlashInPath) {
+        // NO-OP
+    }
+    @Override
+    public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; 
}
 }
\ No newline at end of file

Modified: tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/unittest/TesterContext.java Fri Apr 27 
17:14:19 2018
@@ -1266,4 +1266,12 @@ public class TesterContext implements Co
     public void setResponseCharacterEncoding(String encoding) { /* NO-OP */ }
     @Override
     public String getResponseCharacterEncoding() { return null; }
+
+    @Override
+    public void setAllowMultipleLeadingForwardSlashInPath(
+            boolean allowMultipleLeadingForwardSlashInPath) {
+        // NO-OP
+    }
+    @Override
+    public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; 
}
 }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri Apr 27 17:14:19 2018
@@ -86,6 +86,14 @@
         <bug>62329</bug>: Correctly list resources in JAR files when 
directories
         do not have dedicated entries. Patch provided by Meelis Müür. (markt)
       </fix>
+      <add>
+        Collapse multiple leading <code>/</code> characters to a single
+        <code>/</code> in the return value of
+        <code>HttpServletRequest#getContextPath()</code> to avoid issues if the
+        value is used with <code>HttpServletResponse#sendRedirect()</code>. 
This
+        behaviour is enabled by default and configurable via the new Context
+        attribute <code>allowMultipleLeadingForwardSlashInPath</code>. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">

Modified: tomcat/trunk/webapps/docs/config/context.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1830367&r1=1830366&r2=1830367&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Fri Apr 27 17:14:19 2018
@@ -269,6 +269,24 @@
         The default is <code>false</code></p>
       </attribute>
 
+      <attribute name="allowMultipleLeadingForwardSlashInPath" 
required="false">
+        <p>Tomcat normalises sequences of multiple <code>/</code> characters in
+        a URI to a single <code>/</code>. This is for consistencuy with the
+        behaviour of file systems as URIs are often translated to file system
+        paths. As a result, the return value of
+        <code>HttpServletRequest#getContextPath()</code> is expected to start
+        with multiple <code>/</code> characters for some URIs. This will cause
+        problems if this value is used directly with
+        <code>HttpServletResponse#sendRedirect()</code> as redirect paths that
+        start with <code>//</code> are treated as protocol relative redirects.
+        To avoid potential issues, Tomcat will collapse multiple leading
+        <code>/</code> characters at the start of the return value for
+        <code>HttpServletRequest#getContextPath()</code> to a single
+        <code>/</code>. This attribute has a default value of 
<code>false</code>
+        which enables the collapsing of multiple <code>/</code> characters. To
+        disable this behaviour, set this attribute to <code>true</code>.</p>
+      </attribute>
+
       <attribute name="altDDName" required="false">
         <p>The absolute path to the alternative deployment descriptor for this
         context. This overrides the default deployment descriptor located at



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

Reply via email to