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