Author: markt Date: Wed Sep 11 14:19:50 2013 New Revision: 1521864 URL: http://svn.apache.org/r1521864 Log: Add support for limiting the size of chunk extensions when using chunked encoding
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1521834 Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Wed Sep 11 14:19:50 2013 @@ -694,13 +694,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/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java Wed Sep 11 14:19:50 2013 @@ -153,6 +153,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/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProcessor.java Wed Sep 11 14:19:50 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/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java Wed Sep 11 14:19:50 2013 @@ -294,7 +294,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.adapter); processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests()); processor.setKeepAliveTimeout(proto.getKeepAliveTimeout()); Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Wed Sep 11 14:19:50 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/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Wed Sep 11 14:19:50 2013 @@ -259,7 +259,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.adapter); processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests()); processor.setKeepAliveTimeout(proto.getKeepAliveTimeout()); Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Processor.java Wed Sep 11 14:19:50 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/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/Http11Protocol.java Wed Sep 11 14:19:50 2013 @@ -164,7 +164,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.adapter); processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests()); processor.setKeepAliveTimeout(proto.getKeepAliveTimeout()); Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java Wed Sep 11 14:19:50 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/tc7.0.x/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java Wed Sep 11 14:19:50 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/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Sep 11 14:19:50 2013 @@ -215,6 +215,10 @@ <fix> Better adherence to RFC2616 for content-length headers. (markt) </fix> + <fix> + Add support for limiting the size of chunk extensions when using chunked + encoding. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml?rev=1521864&r1=1521863&r2=1521864&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml Wed Sep 11 14:19:50 2013 @@ -399,6 +399,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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org