Author: markt
Date: Fri Dec 12 16:10:15 2014
New Revision: 1644954
URL: http://svn.apache.org/r1644954
Log:
Ensure that the result of calling HttpServletRequest.getContextPath() is
neither decoded nor normalized as required by the Servlet specification.
Modified:
tomcat/tc8.0.x/trunk/ (props changed)
tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties
tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Request.java
tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java
tomcat/tc8.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
Propchange: tomcat/tc8.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Dec 12 16:10:15 2014
@@ -1 +1 @@
-/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644815
+/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644815
Modified:
tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties?rev=1644954&r1=1644953&r2=1644954&view=diff
==============================================================================
---
tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties
(original)
+++
tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/LocalStrings.properties
Fri Dec 12 16:10:15 2014
@@ -34,6 +34,7 @@ coyoteConnector.parseBodyMethodNoTrace=T
coyoteOutputStream.nbNotready=In non-blocking mode you may not write to the
ServletOutputStream until the previous write has completed and isReady()
returns true
+coyoteRequest.getContextPath.ise=Unable to find match between the canonical
context path [{0}] and the URI presented by the user agent [{1}]
coyoteRequest.getInputStream.ise=getReader() has already been called for this
request
coyoteRequest.getReader.ise=getInputStream() has already been called for this
request
coyoteRequest.gssLifetimeFail=Failed to obtain remaining lifetime for user
principal [{0}]
Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Request.java
URL:
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Request.java?rev=1644954&r1=1644953&r2=1644954&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Request.java
(original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Request.java Fri
Dec 12 16:10:15 2014
@@ -84,6 +84,7 @@ import org.apache.tomcat.util.ExceptionU
import org.apache.tomcat.util.buf.B2CConverter;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.buf.UDecoder;
import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.http.Parameters;
@@ -1901,24 +1902,80 @@ public class Request
/**
* Return the portion of the request URI used to select the Context
- * of the Request.
+ * of the Request. The value returned is not decoded which also implies it
+ * is not normalised.
*/
@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 "";
+ }
int pos = 0;
+ // Need at least the number of slashes in the context path
while (lastSlash > 0) {
- pos = uri.indexOf('/', pos + 1);
+ pos = nextSlash(uriChars, pos + 1);
if (pos == -1) {
- return uri;
+ break;
}
lastSlash--;
}
- return uri.substring(0, pos);
+ // Now allow for normalization and/or encoding. Essentially, keep
+ // extending the candidate path up to the next slash until the decoded
+ // and normalized candidate path is the same as the canonical path.
+ String candidate;
+ if (pos == -1) {
+ candidate = uri;
+ } else {
+ candidate = uri.substring(0, pos);
+ }
+ candidate = UDecoder.URLDecode(candidate, connector.getURIEncoding());
+ candidate =
org.apache.tomcat.util.http.RequestUtil.normalize(candidate);
+ boolean match = canonicalContextPath.equals(candidate);
+ while (!match && pos != -1) {
+ pos = nextSlash(uriChars, pos + 1);
+ if (pos == -1) {
+ candidate = uri;
+ } else {
+ candidate = uri.substring(0, pos);
+ }
+ candidate = UDecoder.URLDecode(candidate,
connector.getURIEncoding());
+ candidate =
org.apache.tomcat.util.http.RequestUtil.normalize(candidate);
+ match = canonicalContextPath.equals(candidate);
+ }
+ if (match) {
+ if (pos == -1) {
+ return uri;
+ } else {
+ return uri.substring(0, pos);
+ }
+ } else {
+ // Should never happen
+ throw new IllegalStateException(sm.getString(
+ "coyoteRequest.getContextPath.ise", canonicalContextPath,
uri));
+ }
}
+ private int nextSlash(char[] uri, int startPos) {
+ int len = uri.length;
+ int pos = startPos;
+ while (pos < len) {
+ if (uri[pos] == '/') {
+ return pos;
+ } else if (UDecoder.ALLOW_ENCODED_SLASH && uri[pos] == '%' && pos
+ 2 < len &&
+ uri[pos+1] == '2' && (uri[pos + 2] == 'f' || uri[pos + 2]
== 'F')) {
+ return pos;
+ }
+ pos++;
+ }
+ return -1;
+ }
+
/**
* Return the set of Cookies received with this Request. Triggers parsing
of
* the Cookie HTTP headers followed by conversion to Cookie objects if this
Modified: tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java
URL:
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java?rev=1644954&r1=1644953&r2=1644954&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java
(original)
+++ tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java Fri Dec
12 16:10:15 2014
@@ -40,7 +40,7 @@ public final class UDecoder {
private static final Log log = LogFactory.getLog(UDecoder.class);
- private static final boolean ALLOW_ENCODED_SLASH =
+ public static final boolean ALLOW_ENCODED_SLASH =
Boolean.valueOf(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH",
"false")).booleanValue();
private static class DecodeException extends CharConversionException {
Modified:
tomcat/tc8.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
URL:
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java?rev=1644954&r1=1644953&r2=1644954&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
(original)
+++ tomcat/tc8.0.x/trunk/test/org/apache/catalina/connector/TestRequest.java
Fri Dec 12 16:10:15 2014
@@ -41,6 +41,7 @@ import static org.junit.Assert.assertTru
import static org.junit.Assert.fail;
import org.junit.Assert;
+import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
@@ -61,6 +62,12 @@ import org.apache.tomcat.util.descriptor
*/
public class TestRequest extends TomcatBaseTest {
+ @BeforeClass
+ public static void setup() {
+ // Some of these tests need this and it used statically so set it once
+
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH",
"true");
+ }
+
/**
* Test case for https://issues.apache.org/bugzilla/show_bug.cgi?id=37794
* POST parameters are not returned from a call to
@@ -762,6 +769,36 @@ public class TestRequest extends TomcatB
doBug56501("/pa_th/abc", "/pa_th/abc/xxx", "/pa_th/abc");
}
+ @Test
+ public void testBug57215a() throws Exception {
+ doBug56501("/path", "//path", "//path");
+ }
+
+ @Test
+ public void testBug57215b() throws Exception {
+ doBug56501("/path", "//path/", "//path");
+ }
+
+ @Test
+ public void testBug57215c() throws Exception {
+ doBug56501("/path", "/%2Fpath", "/%2Fpath");
+ }
+
+ @Test
+ public void testBug57215d() throws Exception {
+ doBug56501("/path", "/%2Fpath%2F", "/%2Fpath");
+ }
+
+ @Test
+ public void testBug57215e() throws Exception {
+ doBug56501("/path", "/foo/../path", "/foo/../path");
+ }
+
+ @Test
+ public void testBug57215f() throws Exception {
+ doBug56501("/path", "/foo/..%2fpath", "/foo/..%2fpath");
+ }
+
private void doBug56501(String deployPath, String requestPath, String
expected)
throws Exception {
Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1644954&r1=1644953&r2=1644954&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Fri Dec 12 16:10:15 2014
@@ -71,6 +71,11 @@
a patch provided by Jason McIntosh. (violetagg)
</fix>
<fix>
+ <bug>57215</bug>: Ensure that the result of calling
+ <code>HttpServletRequest.getContextPath()</code> is neither decoded nor
+ normalized as required by the Servlet specification. (markt)
+ </fix>
+ <fix>
<bug>57216</bug>: Improve handling of invalid context paths. A context
path should either be an empty string or start with a
<code>'/'</code> and do not end with a
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]