VYPR
Moderate severityNVD Advisory· Published Feb 26, 2014· Updated Apr 29, 2026

CVE-2013-4322

CVE-2013-4322

Description

Apache Tomcat processes chunked transfer coding improperly, allowing remote attackers to cause a denial of service by streaming large amounts of chunked data or exploiting whitespace characters in trailer header values.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Apache Tomcat processes chunked transfer coding improperly, allowing remote attackers to cause a denial of service by streaming large amounts of chunked data or exploiting whitespace characters in trailer header values.

Vulnerability

CVE-2013-4322 is an incomplete fix for CVE-2012-3544 affecting Apache Tomcat handling of chunked transfer coding. The vulnerability exists because Tomcat does not properly handle (1) a large total amount of chunked data or (2) whitespace characters in an HTTP header value within a trailer field [1][2]. This affects Apache Tomcat before 6.0.39, 7.x before 7.0.50, and 8.x before 8.0.0-RC10 [1][2][4].

Exploitation

An attacker requires network access to a vulnerable Tomcat server. The attacker can stream a large amount of chunked data or send crafted HTTP requests with whitespace characters in trailer header values. No authentication is necessary for exploitation; the attacker sends specially crafted HTTP requests to the server, causing the vulnerable parsing logic to be triggered [1][2].

Impact

Successful exploitation leads to a denial of service (DoS). The attacker can consume server resources or cause the Tomcat process to become unresponsive, affecting availability of the web server. There is no disclosure of information or remote code execution; the impact is limited to availability [1][2].

Mitigation

Apache Tomcat fixed this vulnerability in versions 6.0.39, 7.0.50, and 8.0.0-RC10 [1][2][4]. Users should upgrade to these versions or later. Note that Tomcat 6.0.x, 7.0.x, and 8.0.x have reached end of life, and further vulnerabilities in these branches will not be fixed; users are advised to upgrade to currently supported branches such as Tomcat 9.0.x [1][2][4]. Red Hat has provided updated packages for its distributions, such as tomcat-7.0.42-5.el7_0 for Red Hat Enterprise Linux 7 [3]. If upgrading is not immediately possible, consider blocking or restricting HTTP chunked transfer encoding at a reverse proxy or load balancer.

AI Insight generated on May 23, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.tomcat:tomcatMaven
< 6.0.396.0.39
org.apache.tomcat:tomcatMaven
>= 7.0.0, < 7.0.507.0.50
org.apache.tomcat:tomcatMaven
>= 8.0.0-RC1, < 8.0.0-RC108.0.0-RC10

Affected products

192
  • Apache/Tomcat191 versions
    cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*+ 190 more
    • cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*range: <=6.0.37
    • cpe:2.3:a:apache:tomcat:1.1.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.2.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.2.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.2.2:beta2:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.2.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.2.4:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.3.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.3.1a:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:3.3.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.4:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.5:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.0.6:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.10:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.12:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.15:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.24:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.28:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.29:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.31:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.36:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.3:beta:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:4.1.9:beta:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.10:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.11:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.12:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.13:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.14:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.15:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.16:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.17:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.18:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.19:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.21:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.22:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.23:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.24:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.25:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.26:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.27:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.28:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.29:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.30:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.4:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.5:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.6:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.7:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.8:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.0.9:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.10:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.11:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.12:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.13:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.14:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.15:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.16:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.17:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.18:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.19:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.20:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.21:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.22:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.23:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.24:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.25:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.26:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.27:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.28:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.29:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.30:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.31:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.32:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.33:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.34:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.35:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.4:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.5:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.6:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.7:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.8:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:5.5.9:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.0:alpha:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.10:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.11:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.12:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.13:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.14:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.15:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.16:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.17:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.18:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.19:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.1:alpha:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.20:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.24:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.26:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.27:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.28:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.29:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.2:alpha:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.2:beta:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.30:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.31:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.32:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.33:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.35:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:6.0.36:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.0:beta:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.10:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.11:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.12:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.13:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.14:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.15:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.16:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.17:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.18:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.19:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.20:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.21:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.22:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.23:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.24:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.25:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.26:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.27:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.28:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.29:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.2:beta:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.3:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.30:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.31:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.32:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.33:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.34:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.35:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.36:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.37:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.38:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.39:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.4:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.40:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.41:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.42:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.43:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.44:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.45:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.46:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.4:beta:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:7.0.50:*:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc1:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc2:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc3:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc4:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc5:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc6:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc7:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc8:*:*:*:*:*:*
    • cpe:2.3:a:apache:tomcat:8.0.0:rc9:*:*:*:*:*:*
  • ghsa-coords
    Range: < 6.0.39

Patches

6
72613a0e2f88

New field can be final

https://github.com/apache/tomcatMark Emlyn David ThomasDec 9, 2013via ghsa
2 files changed · +4 1
  • java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+1 1 modified
    @@ -128,7 +128,7 @@ public class ChunkedInputFilter implements InputFilter {
         /**
          * Limit for trailer size.
          */
    -    private int maxTrailerSize;
    +    private final int maxTrailerSize;
     
         /**
          * Size of extensions processed for this request.
    
  • webapps/docs/changelog.xml+3 0 modified
    @@ -251,6 +251,9 @@
             protects against misbehaving clients that may not sent the request body
             in that case and send the next request instead. (markt)
           </add>
    +      <fix>
    +        Improve the parsing of trailing headers in HTTP requests. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
70dc3b279f7c

New field can be final

https://github.com/apache/tomcatMark Emlyn David ThomasDec 9, 2013via ghsa
1 file changed · +1 1
  • java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+1 1 modified
    @@ -128,7 +128,7 @@ public class ChunkedInputFilter implements InputFilter {
         /**
          * Limit for trailer size.
          */
    -    private int maxTrailerSize;
    +    private final int maxTrailerSize;
     
         /**
          * Size of extensions processed for this request.
    
a91516b80dea

Improve parsing of trailing headers

https://github.com/apache/tomcatMark Emlyn David ThomasDec 9, 2013via ghsa
1 file changed · +21 2
  • java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+21 2 modified
    @@ -125,6 +125,11 @@ public class ChunkedInputFilter implements InputFilter {
         private final long maxExtensionSize;
     
     
    +    /**
    +     * Limit for trailer size.
    +     */
    +    private int maxTrailerSize;
    +
         /**
          * Size of extensions processed for this request.
          */
    @@ -135,6 +140,7 @@ public class ChunkedInputFilter implements InputFilter {
         public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize) {
             this.trailingHeaders.setLimit(maxTrailerSize);
             this.maxExtensionSize = maxExtensionSize;
    +        this.maxTrailerSize = maxTrailerSize;
         }
     
         // ---------------------------------------------------- InputBuffer Methods
    @@ -264,6 +270,7 @@ public void recycle() {
             endChunk = false;
             needCRLFParse = false;
             trailingHeaders.recycle();
    +        trailingHeaders.setLimit(maxTrailerSize);
             extensionSize = 0;
         }
     
    @@ -326,7 +333,10 @@ protected boolean parseChunkHeader()
                 if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
                     parseCRLF(false);
                     eol = true;
    -            } else if (buf[pos] == Constants.SEMI_COLON) {
    +            } else if (buf[pos] == Constants.SEMI_COLON && !extension) {
    +                // First semi-colon marks the start of the extension. Further
    +                // semi-colons may appear to separate multiple chunk-extensions.
    +                // These need to be processed as part of parsing the extensions.
                     extension = true;
                     extensionSize++;
                 } else if (!extension) {
    @@ -342,7 +352,9 @@ protected boolean parseChunkHeader()
                         return false;
                     }
                 } else {
    -                // extension
    +                // Extension 'parsing'
    +                // Note that the chunk-extension is neither parsed nor
    +                // validated. Currently it is simply ignored.
                     extensionSize++;
                     if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
                         throw new IOException("maxExtensionSize exceeded");
    @@ -511,6 +523,13 @@ private boolean parseHeader() throws IOException {
                     chr = buf[pos];
                     if ((chr == Constants.SP) || (chr == Constants.HT)) {
                         pos++;
    +                    // If we swallow whitespace, make sure it counts towards the
    +                    // limit placed on trailing header size
    +                    int newlimit = trailingHeaders.getLimit() -1;
    +                    if (trailingHeaders.getEnd() > newlimit) {
    +                        throw new IOException("Exceeded maxTrailerSize");
    +                    }
    +                    trailingHeaders.setLimit(newlimit);
                     } else {
                         space = false;
                     }
    
b8cb9f5f91e9

Improve parsing of trailing headers

https://github.com/apache/tomcatMark Emlyn David ThomasDec 9, 2013via ghsa
1 file changed · +21 2
  • java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+21 2 modified
    @@ -125,6 +125,11 @@ public class ChunkedInputFilter implements InputFilter {
         private final long maxExtensionSize;
     
     
    +    /**
    +     * Limit for trailer size.
    +     */
    +    private int maxTrailerSize;
    +
         /**
          * Size of extensions processed for this request.
          */
    @@ -135,6 +140,7 @@ public class ChunkedInputFilter implements InputFilter {
         public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize) {
             this.trailingHeaders.setLimit(maxTrailerSize);
             this.maxExtensionSize = maxExtensionSize;
    +        this.maxTrailerSize = maxTrailerSize;
         }
     
         // ---------------------------------------------------- InputBuffer Methods
    @@ -264,6 +270,7 @@ public void recycle() {
             endChunk = false;
             needCRLFParse = false;
             trailingHeaders.recycle();
    +        trailingHeaders.setLimit(maxTrailerSize);
             extensionSize = 0;
         }
     
    @@ -326,7 +333,10 @@ protected boolean parseChunkHeader()
                 if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
                     parseCRLF(false);
                     eol = true;
    -            } else if (buf[pos] == Constants.SEMI_COLON) {
    +            } else if (buf[pos] == Constants.SEMI_COLON && !extension) {
    +                // First semi-colon marks the start of the extension. Further
    +                // semi-colons may appear to separate multiple chunk-extensions.
    +                // These need to be processed as part of parsing the extensions.
                     extension = true;
                     extensionSize++;
                 } else if (!extension) {
    @@ -342,7 +352,9 @@ protected boolean parseChunkHeader()
                         return false;
                     }
                 } else {
    -                // extension
    +                // Extension 'parsing'
    +                // Note that the chunk-extension is neither parsed nor
    +                // validated. Currently it is simply ignored.
                     extensionSize++;
                     if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
                         throw new IOException("maxExtensionSize exceeded");
    @@ -501,6 +513,13 @@ private boolean parseHeader() throws IOException {
                     chr = buf[pos];
                     if ((chr == Constants.SP) || (chr == Constants.HT)) {
                         pos++;
    +                    // If we swallow whitespace, make sure it counts towards the
    +                    // limit placed on trailing header size
    +                    int newlimit = trailingHeaders.getLimit() -1;
    +                    if (trailingHeaders.getEnd() > newlimit) {
    +                        throw new IOException("Exceeded maxTrailerSize");
    +                    }
    +                    trailingHeaders.setLimit(newlimit);
                     } else {
                         space = false;
                     }
    
bed3a1a0d06a

Add support for limiting the size of chunk extensions when using

https://github.com/apache/tomcatMark Emlyn David ThomasSep 11, 2013via ghsa
12 files changed · +129 15
  • java/org/apache/coyote/http11/AbstractHttp11Processor.java+3 2 modified
    @@ -694,13 +694,14 @@ protected boolean statusDropsConnection(int status) {
         /**
          * 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.
    
  • java/org/apache/coyote/http11/AbstractHttp11Protocol.java+10 0 modified
    @@ -152,6 +152,16 @@ public void setMaxTrailerSize(int maxTrailerSize) {
         }
     
     
    +    /**
    +     * 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
    
  • java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+26 4 modified
    @@ -118,9 +118,23 @@ public class ChunkedInputFilter implements InputFilter {
          */
         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 void recycle() {
             endChunk = false;
             needCRLFParse = false;
             trailingHeaders.recycle();
    +        extensionSize = 0;
         }
     
     
    @@ -299,7 +314,7 @@ protected boolean parseChunkHeader()
             int result = 0;
             boolean eol = false;
             boolean readDigit = false;
    -        boolean trailer = false;
    +        boolean extension = false;
     
             while (!eol) {
     
    @@ -312,8 +327,9 @@ protected boolean parseChunkHeader()
                     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 @@ protected boolean parseChunkHeader()
                         //in the chunked header
                         return false;
                     }
    +            } else {
    +                // extension
    +                extensionSize++;
    +                if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
    +                    throw new IOException("maxExtensionSize exceeded");
    +                }
                 }
     
                 // Parsing the CRLF increments pos
    
  • java/org/apache/coyote/http11/Http11AprProcessor.java+2 2 modified
    @@ -58,7 +58,7 @@ protected Log getLog() {
     
     
         public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
    -            int maxTrailerSize) {
    +            int maxTrailerSize, int maxExtensionSize) {
     
             super(endpoint);
     
    @@ -68,7 +68,7 @@ public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
             outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
             response.setOutputBuffer(outputBuffer);
     
    -        initializeFilters(maxTrailerSize);
    +        initializeFilters(maxTrailerSize, maxExtensionSize);
         }
     
     
    
  • java/org/apache/coyote/http11/Http11AprProtocol.java+1 1 modified
    @@ -294,7 +294,7 @@ protected void longPoll(SocketWrapper<Long> socket,
             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());
    
  • java/org/apache/coyote/http11/Http11NioProcessor.java+2 2 modified
    @@ -63,7 +63,7 @@ protected Log getLog() {
     
     
         public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
    -            int maxTrailerSize) {
    +            int maxTrailerSize, int maxExtensionSize) {
     
             super(endpoint);
     
    @@ -73,7 +73,7 @@ public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
             outputBuffer = new InternalNioOutputBuffer(response, maxHttpHeaderSize);
             response.setOutputBuffer(outputBuffer);
     
    -        initializeFilters(maxTrailerSize);
    +        initializeFilters(maxTrailerSize, maxExtensionSize);
         }
     
     
    
  • java/org/apache/coyote/http11/Http11NioProtocol.java+1 1 modified
    @@ -259,7 +259,7 @@ protected void longPoll(SocketWrapper<NioChannel> socket,
             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());
    
  • java/org/apache/coyote/http11/Http11Processor.java+2 2 modified
    @@ -50,7 +50,7 @@ protected Log getLog() {
     
     
         public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
    -            int maxTrailerSize) {
    +            int maxTrailerSize, int maxExtensionSize) {
     
             super(endpoint);
             
    @@ -60,7 +60,7 @@ public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
             outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
             response.setOutputBuffer(outputBuffer);
     
    -        initializeFilters(maxTrailerSize);
    +        initializeFilters(maxTrailerSize, maxExtensionSize);
         }
     
     
    
  • java/org/apache/coyote/http11/Http11Protocol.java+1 1 modified
    @@ -164,7 +164,7 @@ protected void longPoll(SocketWrapper<Socket> socket,
             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());
    
  • test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java+71 0 modified
    @@ -41,6 +41,7 @@
     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 void testTrailingHeadersSizeLimit() throws Exception {
             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
    
  • webapps/docs/changelog.xml+4 0 modified
    @@ -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">
    
  • webapps/docs/config/http.xml+6 0 modified
    @@ -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>
    
d6a9898125f3

Add support for limiting the size of chunk extensions when using

https://github.com/apache/tomcatMark Emlyn David ThomasSep 11, 2013via ghsa
11 files changed · +125 15
  • java/org/apache/coyote/http11/AbstractHttp11Processor.java+3 2 modified
    @@ -654,13 +654,14 @@ protected boolean statusDropsConnection(int status) {
         /**
          * 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.
    
  • java/org/apache/coyote/http11/AbstractHttp11Protocol.java+10 0 modified
    @@ -144,6 +144,16 @@ public void setMaxTrailerSize(int maxTrailerSize) {
         }
     
     
    +    /**
    +     * 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
    
  • java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+26 4 modified
    @@ -118,9 +118,23 @@ public class ChunkedInputFilter implements InputFilter {
          */
         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 void recycle() {
             endChunk = false;
             needCRLFParse = false;
             trailingHeaders.recycle();
    +        extensionSize = 0;
         }
     
     
    @@ -299,7 +314,7 @@ protected boolean parseChunkHeader()
             int result = 0;
             boolean eol = false;
             boolean readDigit = false;
    -        boolean trailer = false;
    +        boolean extension = false;
     
             while (!eol) {
     
    @@ -312,8 +327,9 @@ protected boolean parseChunkHeader()
                     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 @@ protected boolean parseChunkHeader()
                         //in the chunked header
                         return false;
                     }
    +            } else {
    +                // extension
    +                extensionSize++;
    +                if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
    +                    throw new IOException("maxExtensionSize exceeded");
    +                }
                 }
     
                 // Parsing the CRLF increments pos
    
  • java/org/apache/coyote/http11/Http11AprProcessor.java+2 2 modified
    @@ -58,7 +58,7 @@ protected Log getLog() {
     
     
         public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
    -            int maxTrailerSize) {
    +            int maxTrailerSize, int maxExtensionSize) {
     
             super(endpoint);
     
    @@ -68,7 +68,7 @@ public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint,
             outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize);
             response.setOutputBuffer(outputBuffer);
     
    -        initializeFilters(maxTrailerSize);
    +        initializeFilters(maxTrailerSize, maxExtensionSize);
         }
     
     
    
  • java/org/apache/coyote/http11/Http11AprProtocol.java+1 1 modified
    @@ -318,7 +318,7 @@ protected void longPoll(SocketWrapper<Long> socket,
             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());
    
  • java/org/apache/coyote/http11/Http11NioProcessor.java+2 2 modified
    @@ -63,7 +63,7 @@ protected Log getLog() {
     
     
         public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
    -            int maxTrailerSize) {
    +            int maxTrailerSize, int maxExtensionSize) {
     
             super(endpoint);
     
    @@ -73,7 +73,7 @@ public Http11NioProcessor(int maxHttpHeaderSize, NioEndpoint endpoint,
             outputBuffer = new InternalNioOutputBuffer(response, maxHttpHeaderSize);
             response.setOutputBuffer(outputBuffer);
     
    -        initializeFilters(maxTrailerSize);
    +        initializeFilters(maxTrailerSize, maxExtensionSize);
         }
     
     
    
  • java/org/apache/coyote/http11/Http11NioProtocol.java+1 1 modified
    @@ -281,7 +281,7 @@ protected void longPoll(SocketWrapper<NioChannel> socket,
             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());
    
  • java/org/apache/coyote/http11/Http11Processor.java+2 2 modified
    @@ -50,7 +50,7 @@ protected Log getLog() {
     
     
         public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
    -            int maxTrailerSize) {
    +            int maxTrailerSize, int maxExtensionSize) {
     
             super(endpoint);
     
    @@ -60,7 +60,7 @@ public Http11Processor(int headerBufferSize, JIoEndpoint endpoint,
             outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
             response.setOutputBuffer(outputBuffer);
     
    -        initializeFilters(maxTrailerSize);
    +        initializeFilters(maxTrailerSize, maxExtensionSize);
         }
     
     
    
  • java/org/apache/coyote/http11/Http11Protocol.java+1 1 modified
    @@ -186,7 +186,7 @@ protected void longPoll(SocketWrapper<Socket> socket,
             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());
    
  • test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java+71 0 modified
    @@ -41,6 +41,7 @@
     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 void testTrailingHeadersSizeLimit() throws Exception {
             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
    
  • webapps/docs/config/http.xml+6 0 modified
    @@ -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>
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

62

News mentions

0

No linked articles in our index yet.