Skip to content

Commit 2dd0c92

Browse files
authored
Lower WINDOWS_UPDATE received on (half)closed stream to stream abortion
1 parent f425af4 commit 2dd0c92

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,8 +1059,12 @@ private Task ProcessWindowUpdateFrameAsync()
10591059
{
10601060
if (stream.RstStreamReceived)
10611061
{
1062-
// Hard abort, do not allow any more frames on this stream.
1063-
throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamAborted(_incomingFrame.Type, stream.StreamId), Http2ErrorCode.STREAM_CLOSED);
1062+
// WINDOW_UPDATE received after we have already processed an inbound RST_STREAM for this stream.
1063+
// RFC 7540 (Sections 5.1, 6.9) / RFC 9113 do not explicitly define semantics for WINDOW_UPDATE on a
1064+
// stream in the "closed" state due to a reset by client. We surface it as a stream error (STREAM_CLOSED)
1065+
// rather than aborting the entire connection to keep behavior deterministic and consistent with other servers.
1066+
// https://github.com/dotnet/aspnetcore/issues/63726
1067+
throw new Http2StreamErrorException(_incomingFrame.StreamId, CoreStrings.Http2StreamAborted, Http2ErrorCode.STREAM_CLOSED);
10641068
}
10651069

10661070
if (!stream.TryUpdateOutputWindow(_incomingFrame.WindowUpdateSizeIncrement))

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3355,10 +3355,12 @@ public async Task RST_STREAM_IncompleteRequest_AdditionalWindowUpdateFrame_Conne
33553355
await SendDataAsync(1, new byte[1], endStream: false);
33563356
await SendRstStreamAsync(1);
33573357
await SendWindowUpdateAsync(1, 1024);
3358-
tcs.TrySetResult();
33593358

3360-
await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(ignoreNonGoAwayFrames: false, expectedLastStreamId: 1,
3361-
Http2ErrorCode.STREAM_CLOSED, CoreStrings.FormatHttp2ErrorStreamAborted(Http2FrameType.WINDOW_UPDATE, 1));
3359+
await WaitForStreamErrorAsync(expectedStreamId: 1, Http2ErrorCode.STREAM_CLOSED, CoreStrings.Http2StreamAborted);
3360+
3361+
tcs.TrySetResult(); // Don't let the response start until after the abort
3362+
3363+
await StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
33623364
}
33633365

33643366
[Fact]

0 commit comments

Comments
 (0)