diff --git a/src/Kestrel.Core/Internal/Http2/Http2Connection.cs b/src/Kestrel.Core/Internal/Http2/Http2Connection.cs index 87adced245..cf7f25f287 100644 --- a/src/Kestrel.Core/Internal/Http2/Http2Connection.cs +++ b/src/Kestrel.Core/Internal/Http2/Http2Connection.cs @@ -386,6 +386,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } + if (_incomingFrame.StreamId != 0) + { + throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); + } + if (_incomingFrame.Length != 8) { throw new Http2ConnectionErrorException(Http2ErrorCode.FRAME_SIZE_ERROR); diff --git a/test/Kestrel.Core.Tests/Http2ConnectionTests.cs b/test/Kestrel.Core.Tests/Http2ConnectionTests.cs index df4621a8b2..5a8ea479a3 100644 --- a/test/Kestrel.Core.Tests/Http2ConnectionTests.cs +++ b/test/Kestrel.Core.Tests/Http2ConnectionTests.cs @@ -887,6 +887,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await WaitForConnectionErrorAsync(expectedLastStreamId: 0, expectedErrorCode: Http2ErrorCode.PROTOCOL_ERROR, ignoreNonGoAwayFrames: false); } + [Fact] + public async Task PING_Received_StreamIdNotZero_ConnectionError() + { + await InitializeConnectionAsync(_noopApplication); + + await SendPingWithInvalidStreamIdAsync(streamId: 1); + + await WaitForConnectionErrorAsync(expectedLastStreamId: 0, expectedErrorCode: Http2ErrorCode.PROTOCOL_ERROR, ignoreNonGoAwayFrames: false); + } + [Theory] [InlineData(0)] [InlineData(1)] @@ -1427,6 +1437,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests return SendAsync(pingFrame.Raw); } + private Task SendPingWithInvalidStreamIdAsync(int streamId) + { + Assert.NotEqual(0, streamId); + + var pingFrame = new Http2Frame(); + pingFrame.PreparePing(Http2PingFrameFlags.NONE); + pingFrame.StreamId = streamId; + return SendAsync(pingFrame.Raw); + } + private Task SendPriorityAsync(int streamId) { var priorityFrame = new Http2Frame();