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 2014/06/19 11:31:43 UTC
svn commit: r1603781 - in /tomcat/tc7.0.x/trunk: ./
java/org/apache/coyote/http11/ java/org/apache/coyote/http11/filters/
test/org/apache/catalina/core/ webapps/docs/ webapps/docs/config/
Author: markt
Date: Thu Jun 19 09:31:43 2014
New Revision: 1603781
URL: http://svn.apache.org/r1603781
Log:
Add a new limit, defaulting to 2MB, for the amount of data Tomcat will swallow for an aborted upload.
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/java/org/apache/coyote/http11/filters/IdentityInputFilter.java
tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/LocalStrings.properties
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestSwallowAbortedUploads.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:r1603770,1603775,1603779
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -683,14 +683,15 @@ public abstract class AbstractHttp11Proc
/**
* Initialize standard input and output filters.
*/
- protected void initializeFilters(int maxTrailerSize, int maxExtensionSize) {
+ protected void initializeFilters(int maxTrailerSize, int maxExtensionSize,
+ int maxSwallowSize) {
// Create and add the identity filters.
- getInputBuffer().addFilter(new IdentityInputFilter());
+ getInputBuffer().addFilter(new IdentityInputFilter(maxSwallowSize));
getOutputBuffer().addFilter(new IdentityOutputFilter());
// Create and add the chunked filters.
getInputBuffer().addFilter(
- new ChunkedInputFilter(maxTrailerSize, maxExtensionSize));
+ new ChunkedInputFilter(maxTrailerSize, maxExtensionSize, maxSwallowSize));
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -163,6 +163,16 @@ public abstract class AbstractHttp11Prot
/**
+ * Maximum amount of request body to swallow.
+ */
+ private int maxSwallowSize = 2 * 1024 * 1024;
+ public int getMaxSwallowSize() { return maxSwallowSize; }
+ public void setMaxSwallowSize(int maxSwallowSize) {
+ this.maxSwallowSize = maxSwallowSize;
+ }
+
+
+ /**
* 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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -59,7 +59,7 @@ public class Http11AprProcessor extends
public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
- int maxTrailerSize, int maxExtensionSize) {
+ int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {
super(endpoint);
@@ -69,7 +69,7 @@ public class Http11AprProcessor extends
outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
response.setOutputBuffer(outputBuffer);
- initializeFilters(maxTrailerSize, maxExtensionSize);
+ initializeFilters(maxTrailerSize, maxExtensionSize, maxSwallowSize);
}
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -300,7 +300,8 @@ public class Http11AprProtocol extends A
protected Http11AprProcessor createProcessor() {
Http11AprProcessor processor = new Http11AprProcessor(
proto.getMaxHttpHeaderSize(), (AprEndpoint)proto.endpoint,
- proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
+ proto.getMaxTrailerSize(), proto.getMaxExtensionSize(),
+ proto.getMaxSwallowSize());
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -64,7 +64,7 @@ public class Http11NioProcessor extends
public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
- int maxTrailerSize, int maxExtensionSize) {
+ int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {
super(endpoint);
@@ -74,7 +74,7 @@ public class Http11NioProcessor extends
outputBuffer = new InternalNioOutputBuffer(response, maxHttpHeaderSize);
response.setOutputBuffer(outputBuffer);
- initializeFilters(maxTrailerSize, maxExtensionSize);
+ initializeFilters(maxTrailerSize, maxExtensionSize, maxSwallowSize);
}
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -259,7 +259,8 @@ public class Http11NioProtocol extends A
public Http11NioProcessor createProcessor() {
Http11NioProcessor processor = new Http11NioProcessor(
proto.getMaxHttpHeaderSize(), (NioEndpoint)proto.endpoint,
- proto.getMaxTrailerSize(), proto.getMaxExtensionSize());
+ proto.getMaxTrailerSize(), proto.getMaxExtensionSize(),
+ proto.getMaxSwallowSize());
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -50,7 +50,7 @@ public class Http11Processor extends Abs
public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
- int maxTrailerSize, int maxExtensionSize) {
+ int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {
super(endpoint);
@@ -60,7 +60,7 @@ public class Http11Processor extends Abs
outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
response.setOutputBuffer(outputBuffer);
- initializeFilters(maxTrailerSize, maxExtensionSize);
+ initializeFilters(maxTrailerSize, maxExtensionSize, maxSwallowSize);
}
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -164,7 +164,8 @@ public class Http11Protocol extends Abst
protected Http11Processor createProcessor() {
Http11Processor processor = new Http11Processor(
proto.getMaxHttpHeaderSize(), (JIoEndpoint)proto.endpoint,
- proto.getMaxTrailerSize(),proto.getMaxExtensionSize());
+ proto.getMaxTrailerSize(),proto.getMaxExtensionSize(),
+ proto.getMaxSwallowSize());
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=1603781&r1=1603780&r2=1603781&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 Thu Jun 19 09:31:43 2014
@@ -138,6 +138,9 @@ public class ChunkedInputFilter implemen
private long extensionSize;
+ private final int maxSwallowSize;
+
+
/**
* Flag that indicates if an error has occurred.
*/
@@ -146,10 +149,11 @@ public class ChunkedInputFilter implemen
// ----------------------------------------------------------- Constructors
- public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize) {
+ public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {
this.trailingHeaders.setLimit(maxTrailerSize);
this.maxExtensionSize = maxExtensionSize;
this.maxTrailerSize = maxTrailerSize;
+ this.maxSwallowSize = maxSwallowSize;
}
@@ -235,9 +239,14 @@ public class ChunkedInputFilter implemen
*/
@Override
public long end() throws IOException {
+ long swallowed = 0;
+ int read = 0;
// Consume extra bytes : parse the stream until the end chunk is found
- while (doRead(readChunk, null) >= 0) {
- // NOOP: Just consume the input
+ while ((read = doRead(readChunk, null)) >= 0) {
+ swallowed += read;
+ if (maxSwallowSize > -1 && swallowed > maxSwallowSize) {
+ throwIOException(sm.getString("inputFilter.maxSwallow"));
+ }
}
// Return the number of extra bytes which were consumed
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java?rev=1603781&r1=1603780&r2=1603781&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java Thu Jun 19 09:31:43 2014
@@ -24,6 +24,7 @@ import org.apache.coyote.InputBuffer;
import org.apache.coyote.Request;
import org.apache.coyote.http11.InputFilter;
import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.res.StringManager;
/**
* Identity input filter.
@@ -32,6 +33,9 @@ import org.apache.tomcat.util.buf.ByteCh
*/
public class IdentityInputFilter implements InputFilter {
+ private static final StringManager sm = StringManager.getManager(
+ IdentityInputFilter.class.getPackage().getName());
+
// -------------------------------------------------------------- Constants
@@ -76,8 +80,10 @@ public class IdentityInputFilter impleme
protected ByteChunk endChunk = new ByteChunk();
- // ------------------------------------------------------------- Properties
+ private final int maxSwallowSize;
+
+ // ------------------------------------------------------------- Properties
/**
* Get content length.
@@ -101,6 +107,13 @@ public class IdentityInputFilter impleme
}
+ // ------------------------------------------------------------ Constructor
+
+ public IdentityInputFilter(int maxSwallowSize) {
+ this.maxSwallowSize = maxSwallowSize;
+ }
+
+
// ---------------------------------------------------- InputBuffer Methods
@@ -163,8 +176,11 @@ public class IdentityInputFilter impleme
* End the current request.
*/
@Override
- public long end()
- throws IOException {
+ public long end() throws IOException {
+
+ if (maxSwallowSize > -1 && remaining > maxSwallowSize) {
+ throw new IOException(sm.getString("inputFilter.maxSwallow"));
+ }
// Consume extra bytes.
while (remaining > 0) {
Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/LocalStrings.properties?rev=1603781&r1=1603780&r2=1603781&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/LocalStrings.properties (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/filters/LocalStrings.properties Thu Jun 19 09:31:43 2014
@@ -22,4 +22,6 @@ chunkedInputFilter.invalidCrlfNoCR=Inval
chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read)
chunkedInputFilter.invalidHeader=Invalid chunk header
chunkedInputFilter.maxExtension=maxExtensionSize exceeded
-chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
\ No newline at end of file
+chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
+
+inputFilter.maxSwallow=maxSwallowSize exceeded
\ No newline at end of file
Modified: tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestSwallowAbortedUploads.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestSwallowAbortedUploads.java?rev=1603781&r1=1603780&r2=1603781&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestSwallowAbortedUploads.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestSwallowAbortedUploads.java Thu Jun 19 09:31:43 2014
@@ -16,8 +16,14 @@
*/
package org.apache.catalina.core;
+import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.io.Writer;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
@@ -32,6 +38,7 @@ import javax.servlet.http.Part;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import org.junit.Assert;
import org.junit.Test;
import org.apache.catalina.Context;
@@ -113,7 +120,7 @@ public class TestSwallowAbortedUploads e
Exception ex = doAbortedUploadTest(client, true, true);
assertNull("Limited upload with swallow enabled generates client exception",
ex);
- assertTrue("Limited upload with swallow enabled returns error status code",
+ assertTrue("Limited upload with swallow enabled returns non-500 status code",
client.isResponse500());
client.reset();
}
@@ -410,4 +417,78 @@ public class TestSwallowAbortedUploads e
}
}
+
+ @Test
+ public void testChunkedPUTLimit() throws Exception {
+ doTestChunkedPUT(true);
+ }
+
+
+ @Test
+ public void testChunkedPUTNoLimit() throws Exception {
+ doTestChunkedPUT(false);
+ }
+
+
+ public void doTestChunkedPUT(boolean limit) throws Exception {
+
+ Tomcat tomcat = getTomcatInstance();
+ tomcat.addContext("", TEMP_DIR);
+ // No need for target to exist.
+
+ if (!limit) {
+ tomcat.getConnector().setAttribute("maxSwallowSize", "-1");
+ }
+
+ tomcat.start();
+
+ Exception writeEx = null;
+ Exception readEx = null;
+ String responseLine = null;
+ Socket conn = null;
+
+ try {
+ conn = new Socket("localhost", getPort());
+ Writer writer = new OutputStreamWriter(
+ conn.getOutputStream(), StandardCharsets.US_ASCII);
+ writer.write("PUT /does-not-exist HTTP/1.1\r\n");
+ writer.write("Host: any\r\n");
+ writer.write("Transfer-encoding: chunked\r\n");
+ writer.write("\r\n");
+
+ // Smarter than the typical client. Attempts to read the response
+ // even if the request is not fully written.
+ try {
+ // Write (or try to write) 16MB
+ for (int i = 0; i < 1024 * 1024; i++) {
+ writer.write("10\r\n");
+ writer.write("0123456789ABCDEF\r\n");
+ }
+ } catch (Exception e) {
+ writeEx = e;
+ }
+
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ conn.getInputStream(), StandardCharsets.US_ASCII));
+
+ responseLine = reader.readLine();
+ } catch (IOException e) {
+ readEx = e;
+ }
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ if (limit) {
+ Assert.assertNotNull(writeEx);
+ } else {
+ Assert.assertNull(writeEx);
+ Assert.assertNull(readEx);
+ Assert.assertNotNull(responseLine);
+ Assert.assertTrue(responseLine.contains("404"));
+ }
+ }
}
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=1603781&r1=1603780&r2=1603781&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Thu Jun 19 09:31:43 2014
@@ -147,6 +147,10 @@
HTTP connector and ensure that access log entries generated by error
conditions use the correct request start time. (markt)
</fix>
+ <add>
+ Add a new limit, defaulting to 2MB, for the amount of data Tomcat will
+ swallow for an aborted upload. (markt)
+ </add>
</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=1603781&r1=1603780&r2=1603781&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/config/http.xml Thu Jun 19 09:31:43 2014
@@ -431,6 +431,16 @@
If not specified, this attribute is set to 100.</p>
</attribute>
+ <attribute name="maxSwallowSize" required="false">
+ <p>The maximum number of request body bytes (excluding transfer encoding
+ overhead) that will be swallowed by Tomcat for an aborted upload. An
+ aborted upload is when Tomcat knows that the request body is going to be
+ ignored but the client still sends it. If Tomcat does not swallow the body
+ the client is unlikely to see the response. If not specified the default
+ of 2097152 (2 megabytes) will be used. A value of less than zero indicates
+ that no limit should be enforced.</p>
+ </attribute>
+
<attribute name="maxThreads" required="false">
<p>The maximum number of request processing threads to be created
by this <strong>Connector</strong>, which therefore determines the
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org