Author: markt
Date: Mon Nov 17 07:37:36 2014
New Revision: 1640083
URL: http://svn.apache.org/r1640083
Log:
Fix BZ 57215. Ensure that the value returned by
HttpServletRequest.getContextPath() is not decoded which also implies it
has not been normalized.
Modified:
tomcat/trunk/java/org/apache/catalina/connector/Request.java
tomcat/trunk/java/org/apache/tomcat/util/buf/UDecoder.java
tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java
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=1640083&r1=1640082&r2=1640083&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Mon Nov 17
07:37:36 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;
@@ -1871,24 +1872,60 @@ 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;
int pos = 0;
+ // Need at least the number of slashed in the context path
while (lastSlash > 0) {
- pos = uri.indexOf('/', pos + 1);
+ pos = nextSlash(uriChars, pos + 1);
if (pos == -1) {
return uri;
}
lastSlash--;
}
+ // 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 = uri.substring(0, pos);
+ if (pos > 0) {
+ candidate = UDecoder.URLDecode(candidate);
+ candidate =
org.apache.tomcat.util.http.RequestUtil.normalize(candidate);
+ }
+ while (!canonicalContextPath.equals(candidate)) {
+ pos = nextSlash(uriChars, pos + 1);
+ if (pos == -1) {
+ return uri;
+ }
+ candidate = uri.substring(0, pos);
+ candidate = UDecoder.URLDecode(candidate);
+ candidate =
org.apache.tomcat.util.http.RequestUtil.normalize(candidate);
+ }
return uri.substring(0, pos);
}
+ 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/trunk/java/org/apache/tomcat/util/buf/UDecoder.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/UDecoder.java?rev=1640083&r1=1640082&r2=1640083&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/UDecoder.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/UDecoder.java Mon Nov 17
07:37:36 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/trunk/test/org/apache/catalina/connector/TestRequest.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java?rev=1640083&r1=1640082&r2=1640083&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java (original)
+++ tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java Mon Nov 17
07:37:36 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 {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]