This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push: new ee8042ffce Provide finder grained control of multi-part requests ee8042ffce is described below commit ee8042ffce4cb9324dfd79efda5984f37bbb6910 Author: Mark Thomas <ma...@apache.org> AuthorDate: Tue Jun 3 16:05:53 2025 +0100 Provide finder grained control of multi-part requests This exposes two new configuration attributes on the Connector: - maxPartCount - maxPartHeaderSize --- java/org/apache/catalina/connector/Connector.java | 24 +++++++++++++++++++ java/org/apache/catalina/connector/Request.java | 28 ++++++++++++++++++----- webapps/docs/changelog.xml | 7 ++++++ webapps/docs/config/ajp.xml | 15 ++++++++++++ webapps/docs/config/http.xml | 15 ++++++++++++ webapps/docs/config/http2.xml | 2 ++ 6 files changed, 85 insertions(+), 6 deletions(-) diff --git a/java/org/apache/catalina/connector/Connector.java b/java/org/apache/catalina/connector/Connector.java index 49d80c8843..59565abf10 100644 --- a/java/org/apache/catalina/connector/Connector.java +++ b/java/org/apache/catalina/connector/Connector.java @@ -204,6 +204,10 @@ public class Connector extends LifecycleMBeanBase { */ protected int maxParameterCount = 10000; + private int maxPartCount = 10; + + private int maxPartHeaderSize = 512; + /** * Maximum size of a POST which will be automatically parsed by the container. 2 MiB by default. */ @@ -463,6 +467,26 @@ public class Connector extends LifecycleMBeanBase { } + public int getMaxPartCount() { + return maxPartCount; + } + + + public void setMaxPartCount(int maxPartCount) { + this.maxPartCount = maxPartCount; + } + + + public int getMaxPartHeaderSize() { + return maxPartHeaderSize; + } + + + public void setMaxPartHeaderSize(int maxPartHeaderSize) { + this.maxPartHeaderSize = maxPartHeaderSize; + } + + /** * @return the maximum size of a POST which will be automatically parsed by the container. */ diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index 6bc8d80964..ccadd497af 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -2630,13 +2630,29 @@ public class Request implements HttpServletRequest { upload.setFileItemFactory(factory); upload.setFileSizeMax(mce.getMaxFileSize()); upload.setSizeMax(mce.getMaxRequestSize()); - if (maxParameterCount > -1) { - // There is a limit. The limit for parts needs to be reduced by - // the number of parameters we have already parsed. - // Must be under the limit else parsing parameters would have - // triggered an exception. - upload.setFileCountMax(maxParameterCount - parameters.size()); + upload.setPartHeaderSizeMax(connector.getMaxPartHeaderSize()); + /* + * There are two independent limits on the number of parts. + * + * 1. The limit based on parameters. This is maxParameterCount less the number of parameters already processed. + * + * 2. The limit based on parts. This is maxPartCount. + * + * The lower of these two limits will be applied to this request. + * + * Note: Either of both limits may be set to -1 (unlimited). + */ + int partLimit = maxParameterCount; + if (partLimit > -1) { + partLimit = partLimit - parameters.size(); + } + int maxPartCount = connector.getMaxPartCount(); + if (maxPartCount > -1) { + if (partLimit < 0 || partLimit > maxPartCount) { + partLimit = maxPartCount; + } } + upload.setFileCountMax(partLimit); parts = new ArrayList<>(); try { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index bd2ee2a8c3..cd3e7743c2 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -146,6 +146,13 @@ <code>BlockingQueue</code> implementation. Pull request provided by Paulo Almeida. (markt) </scode> + <add> + Provide finer grained control of multi-part request processing via two + new attributes on the <code>Connector</code> element. + <code>maxPartCount</code> limits the total number of parts in a + multi-part request and <code>maxPartHeaderSize</code> limits the size of + the headers provided with each part. (markt) + </add> </changelog> </subsection> <subsection name="Jasper"> diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml index 2ee5f5280b..14ce080f37 100644 --- a/webapps/docs/config/ajp.xml +++ b/webapps/docs/config/ajp.xml @@ -175,6 +175,21 @@ exceed the limit.</p> </attribute> + <attribute name="maxPartCount" required="false"> + <p>The maximum total number of parts permitted in a request where the + content type is <code>multipart/form-data</code>. This limit is in + addition to <code>maxParameterCount</code>. Requests that exceed this + limit will be rejected. A value of less than 0 means no limit. If not + specified, a default of 10 is used.</p> + </attribute> + + <attribute name="maxPartHeaderSize" required="false"> + <p>The maximum number of header bytes permitted per part in a request + where the content type is <code>multipart/form-data</code>. Requests that + exceed this limit will be rejected. A value of less than 0 means no limit. + If not specified, a default of 512 is used.</p> + </attribute> + <attribute name="maxPostSize" required="false"> <p>The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing. The limit can be disabled by diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml index 316e02dacd..a12c740fc1 100644 --- a/webapps/docs/config/http.xml +++ b/webapps/docs/config/http.xml @@ -173,6 +173,21 @@ exceed the limit.</p> </attribute> + <attribute name="maxPartCount" required="false"> + <p>The maximum total number of parts permitted in a request where the + content type is <code>multipart/form-data</code>. This limit is in + addition to <code>maxParameterCount</code>. Requests that exceed this + limit will be rejected. A value of less than 0 means no limit. If not + specified, a default of 10 is used.</p> + </attribute> + + <attribute name="maxPartHeaderSize" required="false"> + <p>The maximum number of header bytes permitted per part in a request + where the content type is <code>multipart/form-data</code>. Requests that + exceed this limit will be rejected. A value of less than 0 means no limit. + If not specified, a default of 512 is used.</p> + </attribute> + <attribute name="maxPostSize" required="false"> <p>The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing. The limit can be disabled by diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml index 78ec1fe79b..0a0d98cb32 100644 --- a/webapps/docs/config/http2.xml +++ b/webapps/docs/config/http2.xml @@ -317,6 +317,8 @@ <ul> <li>maxCookieCount</li> <li>maxParameterCount</li> + <li>maxPartCount</li> + <li>maxPartHeaderSize</li> <li>maxPostSize</li> <li>maxSavePostSize</li> <li>server</li> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org