diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java index 9bc5b6b15..11c5c39f7 100644 --- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java +++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java @@ -915,12 +915,14 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio if (streamId == 0) { throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Illegal stream id: " + streamId); } + + final ByteBuffer payload = frame.getPayload(); + if (payload == null || payload.remaining() != 4) { + throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid RST_STREAM frame payload"); + } + final H2Stream stream = streams.lookupSeen(streamId); if (stream != null) { - final ByteBuffer payload = frame.getPayload(); - if (payload == null || payload.remaining() != 4) { - throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid RST_STREAM frame payload"); - } final int errorCode = payload.getInt(); if (errorCode == H2Error.NO_ERROR.getCode() && allowGracefulAbort(stream)) { stream.abortGracefully(); diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java index ea16173a3..e792f0405 100644 --- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java +++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java @@ -1931,4 +1931,39 @@ void testFirstPeerSettingsAckRejected() throws Exception { Assertions.assertEquals(H2Error.PROTOCOL_ERROR, H2Error.getByCode(ex.getCode())); } + @Test + void testInputRstStreamWithInvalidLengthOnUnseenStreamRejected() throws Exception { + Mockito.when(protocolIOSession.write(ArgumentMatchers.any(ByteBuffer.class))) + .thenAnswer(invocation -> { + final ByteBuffer buffer = invocation.getArgument(0, ByteBuffer.class); + final int remaining = buffer.remaining(); + buffer.position(buffer.limit()); + return remaining; + }); + Mockito.doNothing().when(protocolIOSession).setEvent(ArgumentMatchers.anyInt()); + Mockito.doNothing().when(protocolIOSession).clearEvent(ArgumentMatchers.anyInt()); + + final AbstractH2StreamMultiplexer mux = new H2StreamMultiplexerImpl( + protocolIOSession, + FRAME_FACTORY, + StreamIdGenerator.ODD, + httpProcessor, + CharCodingConfig.DEFAULT, + H2Config.custom().build(), + h2StreamListener, + () -> streamHandler); + + mux.onConnect(); + completeSettingsHandshake(mux); + + final RawFrame badRst = new RawFrame(FrameType.RST_STREAM.getValue(), 0, 1, null); + + final H2ConnectionException ex = Assertions.assertThrows( + H2ConnectionException.class, + () -> mux.onInput(ByteBuffer.wrap(encodeFrame(badRst)))); + + Assertions.assertEquals(H2Error.FRAME_SIZE_ERROR, H2Error.getByCode(ex.getCode())); + } + + } \ No newline at end of file