diff --git a/src/Kestrel.Core/Internal/Http2/Http2Connection.cs b/src/Kestrel.Core/Internal/Http2/Http2Connection.cs index ae2b7d5bed..87adced245 100644 --- a/src/Kestrel.Core/Internal/Http2/Http2Connection.cs +++ b/src/Kestrel.Core/Internal/Http2/Http2Connection.cs @@ -218,9 +218,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 return ProcessWindowUpdateFrameAsync(); case Http2FrameType.CONTINUATION: return ProcessContinuationFrameAsync(application); + default: + return ProcessUnknownFrameAsync(); } - - return Task.CompletedTask; } private Task ProcessDataFrameAsync() @@ -454,6 +454,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 return Task.CompletedTask; } + private Task ProcessUnknownFrameAsync() + { + if (_currentHeadersStream != null) + { + throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); + } + + return Task.CompletedTask; + } + void IHttp2StreamLifetimeHandler.OnStreamCompleted(int streamId) { _streams.TryRemove(streamId, out _); diff --git a/test/Kestrel.Core.Tests/Http2ConnectionTests.cs b/test/Kestrel.Core.Tests/Http2ConnectionTests.cs index 56bd6f3b31..df4621a8b2 100644 --- a/test/Kestrel.Core.Tests/Http2ConnectionTests.cs +++ b/test/Kestrel.Core.Tests/Http2ConnectionTests.cs @@ -1062,6 +1062,34 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests Assert.Equal(_largeHeaderB, responseHeadersDictionary["b"]); } + [Fact] + public async Task UnknownFrameType_Received_Ignored() + { + await InitializeConnectionAsync(_noopApplication); + + await SendUnknownFrameTypeAsync(streamId: 1); + + // Check that the connection is still alive + await SendPingAsync(); + await ExpectAsync(Http2FrameType.PING, + withLength: 8, + withFlags: (byte)Http2PingFrameFlags.ACK, + withStreamId: 0); + + await StopConnectionAsync(0, ignoreNonGoAwayFrames: false); + } + + [Fact] + public async Task UnknownFrameType_Received_InterleavedWithHeaders_ConnectionError() + { + await InitializeConnectionAsync(_noopApplication); + + await SendHeadersAsync(1, Http2HeadersFrameFlags.NONE, _browserRequestHeaders); + await SendUnknownFrameTypeAsync(streamId: 1); + + await WaitForConnectionErrorAsync(expectedLastStreamId: 0, expectedErrorCode: Http2ErrorCode.PROTOCOL_ERROR, ignoreNonGoAwayFrames: false); + } + [Fact] public async Task ConnectionError_AbortsAllStreams() { @@ -1451,6 +1479,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests return SendAsync(frame.Raw); } + private Task SendUnknownFrameTypeAsync(int streamId) + { + var frame = new Http2Frame(); + frame.StreamId = streamId; + frame.Type = (Http2FrameType)42; + frame.Length = 0; + return SendAsync(frame.Raw); + } + private async Task ReceiveFrameAsync() { var frame = new Http2Frame();