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 eb316d3fc8 Clarify stream flow-control comment; add RST_STREAM 
regression test (#1133)
eb316d3fc8 is described below

commit eb316d3fc81260bd1bbc0bae062b96d2e8549271
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  | 53 ++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/coyote/http2/Http2Parser.java 
b/java/org/apache/coyote/http2/Http2Parser.java
index fca94b82d9..fdb33ce864 100644
--- a/java/org/apache/coyote/http2/Http2Parser.java
+++ b/java/org/apache/coyote/http2/Http2Parser.java
@@ -219,7 +219,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..bb2c4c663a 100644
--- a/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
+++ b/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
@@ -269,4 +269,57 @@ 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).
+        parser.readFrame();
+        parser.readFrame();
+        parser.readFrame();
+        parser.readFrame();
+        parser.readFrame();
+
+        // Confirm the expected SETTINGS frame is present
+        String trace = output.getTrace();
+        Assert.assertTrue(trace, trace.contains("0-Settings-[4]-[1024]"));
+        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() + "]"));
+        output.clearTrace();
+
+        // The connection must still be open and usable for other streams.
+        sendSimpleGetRequest(5);
+        // The response to the upgrade request on stream 1 may still be 
pending so
+        // keep reading until the end of the response on stream 5 has been 
seen.
+        while (!output.getTrace().contains("5-EndOfStream")) {
+            parser.readFrame();
+        }
+        Assert.assertTrue(output.getTrace(), 
output.getTrace().contains(getSimpleResponseTrace(5)));
+    }
 }


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

Reply via email to