You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/09/11 15:44:21 UTC

svn commit: r1521834 - in /tomcat/trunk: java/org/apache/coyote/http11/ java/org/apache/coyote/http11/filters/ test/org/apache/coyote/http11/filters/ webapps/docs/config/

Author: markt
Date: Wed Sep 11 13:44:21 2013
New Revision: 1521834

URL: http://svn.apache.org/r1521834
Log:
Add support for limiting the size of chunk extensions when using
chunked encoding

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
    tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java
    tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
    tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
    tomcat/trunk/webapps/docs/config/http.xml

Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Wed Sep 11 13:44:21 2013
@@ -654,13 +654,14 @@ public abstract class AbstractHttp11Proc
     /**
      * Initialize standard input and output filters.
      */
-    protected void initializeFilters(int maxTrailerSize) {
+    protected void initializeFilters(int maxTrailerSize, int maxExtensionSize) {
         // Create and add the identity filters.
         getInputBuffer().addFilter(new IdentityInputFilter());
         getOutputBuffer().addFilter(new IdentityOutputFilter());
 
         // Create and add the chunked filters.
-        getInputBuffer().addFilter(new ChunkedInputFilter(maxTrailerSize));
+        getInputBuffer().addFilter(
+                new ChunkedInputFilter(maxTrailerSize, maxExtensionSize));
         getOutputBuffer().addFilter(new ChunkedOutputFilter());
 
         // Create and add the void filters.

Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java Wed Sep 11 13:44:21 2013
@@ -145,6 +145,16 @@ public abstract class AbstractHttp11Prot
 
 
     /**
+     * Maximum size of extension information in chunked encoding
+     */
+    private int maxExtensionSize = 8192;
+    public int getMaxExtensionSize() { return maxExtensionSize; }
+    public void setMaxExtensionSize(int maxExtensionSize) {
+        this.maxExtensionSize = maxExtensionSize;
+    }
+
+
+    /**
      * This field indicates if the protocol is treated as if it is secure. This
      * normally means https is being used but can be used to fake https e.g
      * behind a reverse proxy.

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Wed Sep 11 13:44:21 2013
@@ -58,7 +58,7 @@ public class Http11AprProcessor extends 
 
 
     public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
-            int maxTrailerSize) {
+            int maxTrailerSize, int maxExtensionSize) {
 
         super(endpoint);
 
@@ -68,7 +68,7 @@ public class Http11AprProcessor extends 
         outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
         response.setOutputBuffer(outputBuffer);
 
-        initializeFilters(maxTrailerSize);
+        initializeFilters(maxTrailerSize, maxExtensionSize);
     }
 
 

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java Wed Sep 11 13:44:21 2013
@@ -318,7 +318,7 @@ public class Http11AprProtocol extends A
         protected Http11AprProcessor createProcessor() {
             Http11AprProcessor processor = new Http11AprProcessor(
                     proto.getMaxHttpHeaderSize(), (AprEndpoint)proto.endpoint,
-                    proto.getMaxTrailerSize());
+                    proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
             processor.setAdapter(proto.getAdapter());
             processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
             processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Wed Sep 11 13:44:21 2013
@@ -63,7 +63,7 @@ public class Http11NioProcessor extends 
 
 
     public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
-            int maxTrailerSize) {
+            int maxTrailerSize, int maxExtensionSize) {
 
         super(endpoint);
 
@@ -73,7 +73,7 @@ public class Http11NioProcessor extends 
         outputBuffer = new InternalNioOutputBuffer(response, maxHttpHeaderSize);
         response.setOutputBuffer(outputBuffer);
 
-        initializeFilters(maxTrailerSize);
+        initializeFilters(maxTrailerSize, maxExtensionSize);
     }
 
 

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Wed Sep 11 13:44:21 2013
@@ -281,7 +281,7 @@ public class Http11NioProtocol extends A
         public Http11NioProcessor createProcessor() {
             Http11NioProcessor processor = new Http11NioProcessor(
                     proto.getMaxHttpHeaderSize(), (NioEndpoint)proto.endpoint,
-                    proto.getMaxTrailerSize());
+                    proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
             processor.setAdapter(proto.getAdapter());
             processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
             processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Wed Sep 11 13:44:21 2013
@@ -50,7 +50,7 @@ public class Http11Processor extends Abs
 
 
     public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
-            int maxTrailerSize) {
+            int maxTrailerSize, int maxExtensionSize) {
 
         super(endpoint);
 
@@ -60,7 +60,7 @@ public class Http11Processor extends Abs
         outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
         response.setOutputBuffer(outputBuffer);
 
-        initializeFilters(maxTrailerSize);
+        initializeFilters(maxTrailerSize, maxExtensionSize);
     }
 
 

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java Wed Sep 11 13:44:21 2013
@@ -186,7 +186,7 @@ public class Http11Protocol extends Abst
         protected Http11Processor createProcessor() {
             Http11Processor processor = new Http11Processor(
                     proto.getMaxHttpHeaderSize(), (JIoEndpoint)proto.endpoint,
-                    proto.getMaxTrailerSize());
+                    proto.getMaxTrailerSize(),proto.getMaxExtensionSize());
             processor.setAdapter(proto.getAdapter());
             processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests());
             processor.setKeepAliveTimeout(proto.getKeepAliveTimeout());

Modified: tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java Wed Sep 11 13:44:21 2013
@@ -118,9 +118,23 @@ public class ChunkedInputFilter implemen
      */
     private Request request;
 
+
+    /**
+     * Limit for extension size.
+     */
+    private final long maxExtensionSize;
+
+
+    /**
+     * Size of extensions processed for this request.
+     */
+    private long extensionSize;
+
+
     // ----------------------------------------------------------- Constructors
-    public ChunkedInputFilter(int maxTrailerSize) {
+    public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize) {
         this.trailingHeaders.setLimit(maxTrailerSize);
+        this.maxExtensionSize = maxExtensionSize;
     }
 
     // ---------------------------------------------------- InputBuffer Methods
@@ -250,6 +264,7 @@ public class ChunkedInputFilter implemen
         endChunk = false;
         needCRLFParse = false;
         trailingHeaders.recycle();
+        extensionSize = 0;
     }
 
 
@@ -299,7 +314,7 @@ public class ChunkedInputFilter implemen
         int result = 0;
         boolean eol = false;
         boolean readDigit = false;
-        boolean trailer = false;
+        boolean extension = false;
 
         while (!eol) {
 
@@ -312,8 +327,9 @@ public class ChunkedInputFilter implemen
                 parseCRLF(false);
                 eol = true;
             } else if (buf[pos] == Constants.SEMI_COLON) {
-                trailer = true;
-            } else if (!trailer) {
+                extension = true;
+                extensionSize++;
+            } else if (!extension) {
                 //don't read data after the trailer
                 int charValue = HexUtils.getDec(buf[pos]);
                 if (charValue != -1) {
@@ -325,6 +341,12 @@ public class ChunkedInputFilter implemen
                     //in the chunked header
                     return false;
                 }
+            } else {
+                // extension
+                extensionSize++;
+                if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
+                    throw new IOException("maxExtensionSize exceeded");
+                }
             }
 
             // Parsing the CRLF increments pos

Modified: tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java Wed Sep 11 13:44:21 2013
@@ -41,6 +41,7 @@ import org.apache.catalina.startup.Tomca
 public class TestChunkedInputFilter extends TomcatBaseTest {
 
     private static final String LF = "\n";
+    private static final int EXT_SIZE_LIMIT = 10;
 
     @Test
     public void testChunkHeaderCRLF() throws Exception {
@@ -202,6 +203,76 @@ public class TestChunkedInputFilter exte
         assertTrue(client.isResponse500());
     }
 
+
+    @Test
+    public void testExtensionSizeLimitOneBelow() throws Exception {
+        doTestExtensionSizeLimit(EXT_SIZE_LIMIT - 1, true);
+    }
+
+
+    @Test
+    public void testExtensionSizeLimitExact() throws Exception {
+        doTestExtensionSizeLimit(EXT_SIZE_LIMIT, true);
+    }
+
+
+    @Test
+    public void testExtensionSizeLimitOneOver() throws Exception {
+        doTestExtensionSizeLimit(EXT_SIZE_LIMIT + 1, false);
+    }
+
+
+    private void doTestExtensionSizeLimit(int len, boolean ok) throws Exception {
+        // Setup Tomcat instance
+        Tomcat tomcat = getTomcatInstance();
+
+        tomcat.getConnector().setProperty(
+                "maxExtensionSize", Integer.toString(EXT_SIZE_LIMIT));
+
+        // Must have a real docBase - just use temp
+        Context ctx =
+            tomcat.addContext("", System.getProperty("java.io.tmpdir"));
+
+        Tomcat.addServlet(ctx, "servlet", new EchoHeaderServlet());
+        ctx.addServletMapping("/", "servlet");
+
+        tomcat.start();
+
+        String extName = ";foo=";
+        StringBuilder extValue = new StringBuilder(len);
+        for (int i = 0; i < (len - extName.length()); i++) {
+            extValue.append("x");
+        }
+
+        String[] request = new String[]{
+            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
+            "Host: any" + SimpleHttpClient.CRLF +
+            "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
+            "Content-Type: application/x-www-form-urlencoded" +
+                    SimpleHttpClient.CRLF +
+            "Connection: close" + SimpleHttpClient.CRLF +
+            SimpleHttpClient.CRLF +
+            "3" + extName + extValue.toString() + SimpleHttpClient.CRLF +
+            "a=0" + SimpleHttpClient.CRLF +
+            "4" + SimpleHttpClient.CRLF +
+            "&b=1" + SimpleHttpClient.CRLF +
+            "0" + SimpleHttpClient.CRLF +
+            SimpleHttpClient.CRLF };
+
+        TrailerClient client =
+                new TrailerClient(tomcat.getConnector().getLocalPort());
+        client.setRequest(request);
+
+        client.connect();
+        client.processRequest();
+
+        if (ok) {
+            assertTrue(client.isResponse200());
+        } else {
+            assertTrue(client.isResponse500());
+        }
+    }
+
     @Test
     public void testNoTrailingHeaders() throws Exception {
         // Setup Tomcat instance

Modified: tomcat/trunk/webapps/docs/config/http.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1521834&r1=1521833&r2=1521834&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/trunk/webapps/docs/config/http.xml Wed Sep 11 13:44:21 2013
@@ -402,6 +402,12 @@
       and connections are not counted.</p>
     </attribute>
 
+    <attribute name="maxExtensionSize" required="false">
+      <p>Limits the total length of chunk extensions in chunked HTTP requests.
+      If the value is <code>-1</code>, no limit will be imposed. If not
+      specified, the default value of <code>8192</code> will be used.</p>
+    </attribute>
+
     <attribute name="maxHttpHeaderSize" required="false">
       <p>The maximum size of the request and response HTTP header, specified
       in bytes. If not specified, this attribute is set to 8192 (8 KB).</p>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org