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

markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new d4bde84579 Clarify stream flow-control comment; add RST_STREAM 
regression test (#1133)
d4bde84579 is described below

commit d4bde84579b6c3b74a2859bd618e2efaf9f592f5
Author: Arturo Bernal <[email protected]>
AuthorDate: Thu Nov 12 17:33:06 2026 +0100

    Clarify stream flow-control comment; add RST_STREAM regression test (#1133)
    
    When a DATA frame payload exceeds the remaining capacity of the stream's
    receive buffer, Http2Parser throws StreamException(FLOW_CONTROL_ERROR),
    resulting in RST_STREAM. This is a stream-level check: the inBuffer is
    scoped to the per-stream initial window, so the violation affects only
    that stream; the connection and other streams remain open.
    
    RFC 9113, section 6.9, permits either a stream error or a connection
    error for this case (MAY). Tomcat's choice of RST_STREAM is correct and
    avoids unnecessary collateral damage to multiplexed streams.
    
    Adds TestHttp2Section_6_9.testDataFrameExceedsFlowControlWindow as a
    regression guard for this behavior.
---
 java/org/apache/coyote/http2/Http2Parser.java      |  2 +-
 .../apache/coyote/http2/TestHttp2Section_6_9.java  | 39 ++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/coyote/http2/Http2Parser.java 
b/java/org/apache/coyote/http2/Http2Parser.java
index 5566314e7e..ff3adb89a4 100644
--- a/java/org/apache/coyote/http2/Http2Parser.java
+++ b/java/org/apache/coyote/http2/Http2Parser.java
@@ -202,7 +202,7 @@ class Http2Parser {
         } else {
             synchronized (dest) {
                 if (dest.remaining() < dataLength) {
-                    // Client has sent more data than permitted by Window size
+                    // Client has sent more data than permitted by the stream 
flow-control window.
                     swallowPayload(streamId, FrameType.DATA.getId(), 
dataLength, false, buffer);
                     if (Flags.hasPadding(flags)) {
                         swallowPayload(streamId, FrameType.DATA.getId(), 
padLength, true, buffer);
diff --git a/test/org/apache/coyote/http2/TestHttp2Section_6_9.java 
b/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
index 28ad585761..caf8c1804c 100644
--- a/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
+++ b/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
@@ -269,4 +269,43 @@ public class TestHttp2Section_6_9 extends Http2TestBase {
         sendSettings(0, false, new SettingValue(4, 1 << 30));
         handleGoAwayResponse(3, Http2Error.FLOW_CONTROL_ERROR);
     }
+
+
+    @Test
+    public void testDataFrameExceedsFlowControlWindow() throws Exception {
+        // Configure the server with a small initial flow-control window so it
+        // is easy to exceed from a test.
+        enableHttp2();
+        http2Protocol.setInitialWindowSize(1024);
+        configureAndStartWebApplication();
+        openClientConnection();
+        doHttpUpgrade();
+        sendClientPreface();
+
+        // Read initial server frames. The exact count varies (SETTINGS, 
SETTINGS-ACK,
+        // PING, response HEADERS and DATA for the upgrade request on stream 
1).
+        // Keep reading until the SETTINGS frame with INITIAL_WINDOW_SIZE=1024 
is seen.
+        s.setSoTimeout(5000);
+        while (!output.getTrace().contains("0-Settings-[4]-[1024]")) {
+            parser.readFrame();
+        }
+        output.clearTrace();
+
+        // Open a stream so the server expects request body data.
+        sendSimplePostRequest(3, null, false);
+        output.clearTrace();
+
+        // Send 2 kB of data, exceeding the advertised 1 kB stream window.
+        // Expect the stream to be reset with FLOW_CONTROL_ERROR; the 
connection
+        // must remain open because this is a stream-level window violation.
+        sendData(3, new byte[2048]);
+
+        // A connection-level WINDOW_UPDATE may precede the RST_STREAM as a
+        // side-effect of consuming the excess payload.
+        while (!output.getTrace().contains("3-RST-")) {
+            parser.readFrame();
+        }
+        Assert.assertTrue(output.getTrace(),
+                output.getTrace().contains("3-RST-[" + 
Http2Error.FLOW_CONTROL_ERROR.getCode() + "]"));
+    }
 }


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

Reply via email to