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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org