From de61d36379045bfa98cbe5e8c999fe1de971850a Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Fri, 30 Oct 2026 17:09:04 +0100 Subject: [PATCH] Treat interleaved non-CONTINUATION frame on same stream as PROTOCOL_ERROR RFC 9113, section 4.3 states that any frame other than CONTINUATION received while a header block is in progress MUST be treated as a connection error of type PROTOCOL_ERROR. Http2Parser.validateFrame() was using COMPRESSION_ERROR for this case when the offending frame arrived on the same stream as the open header block. Changed the error code to PROTOCOL_ERROR to match the RFC. Add TestHttp2Section_4_3#testHeaderContinuationInterleavedDataSameStream to prove the violation and verify the fix. --- java/org/apache/coyote/http2/Http2Parser.java | 2 +- .../coyote/http2/TestHttp2Section_4_3.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 2b07e2d4e32c..76bf1e96b4bd 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -743,7 +743,7 @@ protected void validateFrame(FrameType expected, FrameType frameType, int stream // NO-OP: RST is OK here } else if (frameType != FrameType.CONTINUATION) { throw new ConnectionException(sm.getString("http2Parser.headers.wrongFrameType", connectionId, - Integer.toString(headersCurrentStream), frameType), Http2Error.COMPRESSION_ERROR); + Integer.toString(headersCurrentStream), frameType), Http2Error.PROTOCOL_ERROR); } } diff --git a/test/org/apache/coyote/http2/TestHttp2Section_4_3.java b/test/org/apache/coyote/http2/TestHttp2Section_4_3.java index 48798b3cd1bf..5d9baeb95dd2 100644 --- a/test/org/apache/coyote/http2/TestHttp2Section_4_3.java +++ b/test/org/apache/coyote/http2/TestHttp2Section_4_3.java @@ -248,4 +248,25 @@ public void testHeaderContinuationNonContiguous() throws Exception { handleGoAwayResponse(3, Http2Error.COMPRESSION_ERROR); } + + + @Test + public void testHeaderContinuationInterleavedDataSameStream() throws Exception { + // HTTP2 upgrade + http2Connect(); + + // Start header block on stream 3 without END_HEADERS + byte[] frameHeader = new byte[9]; + ByteBuffer headersPayload = ByteBuffer.allocate(128); + buildSimpleGetRequestPart1(frameHeader, headersPayload, 3); + writeFrame(frameHeader, headersPayload); + + // Send a DATA frame on the same stream while the header block is open. + // RFC 9113, section 4.3: any frame other than CONTINUATION interleaved + // in a header block MUST be treated as a connection error of type + // PROTOCOL_ERROR. + sendData(3, new byte[0]); + + handleGoAwayResponse(3, Http2Error.PROTOCOL_ERROR); + } }