This is an automated email from the ASF dual-hosted git repository.

markt-asf 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 3bf7fa09b8 Improve HTTP/2 frame payload length validation
3bf7fa09b8 is described below

commit 3bf7fa09b8bc10323ebff8356fb8a2f3ab49dbe9
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Jun 10 16:30:50 2026 +0100

    Improve HTTP/2 frame payload length validation
---
 java/org/apache/coyote/http2/Http2Parser.java      | 16 +++++++++++++
 .../apache/coyote/http2/LocalStrings.properties    |  1 +
 .../apache/coyote/http2/TestHttp2Section_4_2.java  | 27 +++++++++++++++++++++-
 webapps/docs/changelog.xml                         |  4 ++++
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/coyote/http2/Http2Parser.java 
b/java/org/apache/coyote/http2/Http2Parser.java
index d733051ad7..40e0399df8 100644
--- a/java/org/apache/coyote/http2/Http2Parser.java
+++ b/java/org/apache/coyote/http2/Http2Parser.java
@@ -158,6 +158,14 @@ class Http2Parser {
 
         int dataLength;
         if (Flags.hasPadding(flags)) {
+
+            // Frame is too small to contain mandatory frame data (for the 
given flags)
+            if (payloadSize == 0) {
+                throw new 
ConnectionException(sm.getString("http2Parser.processFrame.insufficientPayload",connectionId,
+                        Integer.toString(streamId), 
Integer.toString(FrameType.DATA.getId()),
+                        Integer.toString(flags), 
Integer.toString(payloadSize)), Http2Error.FRAME_SIZE_ERROR);
+            }
+
             if (buffer == null) {
                 byte[] b = new byte[1];
                 input.fill(true, b);
@@ -264,6 +272,14 @@ class Http2Parser {
         if (priority) {
             optionalLen += 5;
         }
+
+        // Frame is too small to contain mandatory frame data (for the given 
flags)
+        if (payloadSize < optionalLen) {
+            throw new 
ConnectionException(sm.getString("http2Parser.processFrame.insufficientPayload",connectionId,
+                    Integer.toString(streamId), 
Integer.toString(FrameType.HEADERS.getId()),
+                    Integer.toString(flags), Integer.toString(payloadSize)), 
Http2Error.FRAME_SIZE_ERROR);
+        }
+
         if (optionalLen > 0) {
             byte[] optional = new byte[optionalLen];
             if (buffer == null) {
diff --git a/java/org/apache/coyote/http2/LocalStrings.properties 
b/java/org/apache/coyote/http2/LocalStrings.properties
index f9ee07e151..2cbb11161d 100644
--- a/java/org/apache/coyote/http2/LocalStrings.properties
+++ b/java/org/apache/coyote/http2/LocalStrings.properties
@@ -75,6 +75,7 @@ http2Parser.payloadTooBig=The payload is [{0}] bytes long but 
the maximum frame
 http2Parser.preface.invalid=Invalid connection preface presented
 http2Parser.preface.io=Unable to read connection preface
 http2Parser.processFrame=Connection [{0}], Stream [{1}], Frame type [{2}], 
Flags [{3}], Payload size [{4}]
+http2Parser.processFrame.insufficientPayload=Connection [{0}], Stream [{1}], 
Frame type [{2}] with Flags [{3}] requires a larger payload than [{4}]
 http2Parser.processFrame.tooMuchPadding=Connection [{0}], Stream [{1}], The 
padding length [{2}] was too big for the payload [{3}]
 http2Parser.processFrame.unexpectedType=Expected frame type [{0}] but received 
frame type [{1}]
 http2Parser.processFrameContinuation.notExpected=Connection [{0}], 
Continuation frame received for stream [{1}] when no headers were in progress
diff --git a/test/org/apache/coyote/http2/TestHttp2Section_4_2.java 
b/test/org/apache/coyote/http2/TestHttp2Section_4_2.java
index d73a2495a7..3745fbe07e 100644
--- a/test/org/apache/coyote/http2/TestHttp2Section_4_2.java
+++ b/test/org/apache/coyote/http2/TestHttp2Section_4_2.java
@@ -81,7 +81,7 @@ public class TestHttp2Section_4_2 extends Http2TestBase {
 
 
     @Test
-    public void testFrameTypeLimitsTooSmall() throws Exception {
+    public void testFrameTypeLimitsTooSmallPing() throws Exception {
         // HTTP2 upgrade
         http2Connect();
 
@@ -103,6 +103,31 @@ public class TestHttp2Section_4_2 extends Http2TestBase {
     }
 
 
+    @Test
+    public void testFrameTypeLimitsTooSmallHeaders() throws Exception {
+        // HTTP2 upgrade
+        http2Connect();
+
+        // Too small headers
+        byte[] headers = new byte[9];
+
+        // Header
+        // Length 0
+        // Type
+        headers[3] = FrameType.HEADERS.getIdByte();
+        // Set flags: End headers 0x04, Priority 0x20
+        headers[4] =  0x24;
+        // Stream 3
+        ByteUtil.set31Bits(headers, 5, 3);
+        // Empty payload
+
+        os.write(headers);
+        os.flush();
+
+        handleGoAwayResponse(1, Http2Error.FRAME_SIZE_ERROR);
+    }
+
+
     @Test
     public void testFrameTypeLimitsStream() throws Exception {
         // HTTP2 upgrade
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 38bed9c45d..46dd3394cb 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -334,6 +334,10 @@
         <code>@STRENGTH</code> was encountered, ignoring any subsequent
         expressions. (markt)
       </fix>
+      <fix>
+        Handle the case where the HTTP/2 payload length is insufficient for the
+        mandatory data required by the flags set in the header. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Jasper">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to