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

Reply via email to