Skip to content

Commit 59f6b85

Browse files
authored
HPACK circular overflow #12190 (#12782)
1 parent 001b54f commit 59f6b85

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

src/Servers/Kestrel/Core/src/Internal/Http2/HPack/DynamicTable.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.HPack
77
{
8+
// The dynamic table is defined as a queue where items are inserted at the front and removed from the back.
9+
// It's implemented as a circular buffer that appends to the end and trims from the front. Thus index are reversed.
810
internal class DynamicTable
911
{
1012
private HeaderField[] _buffer;
@@ -35,7 +37,13 @@ public HeaderField this[int index]
3537
throw new IndexOutOfRangeException();
3638
}
3739

38-
return _buffer[_insertIndex == 0 ? _buffer.Length - 1 : _insertIndex - index - 1];
40+
var modIndex = _insertIndex - index - 1;
41+
if (modIndex < 0)
42+
{
43+
modIndex += _buffer.Length;
44+
}
45+
46+
return _buffer[modIndex];
3947
}
4048
}
4149

src/Servers/Kestrel/Core/test/DynamicTableTests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -58,6 +58,22 @@ public void FirstEntryIsMostRecentEntry()
5858
VerifyTableEntries(dynamicTable, _header2, _header1);
5959
}
6060

61+
[Fact]
62+
public void WrapsAroundBuffer()
63+
{
64+
var header3 = new HeaderField(Encoding.ASCII.GetBytes("header-3"), Encoding.ASCII.GetBytes("value3"));
65+
var header4 = new HeaderField(Encoding.ASCII.GetBytes("header-4"), Encoding.ASCII.GetBytes("value4"));
66+
67+
// Make the table small enough that the circular buffer kicks in.
68+
var dynamicTable = new DynamicTable(HeaderField.RfcOverhead * 3);
69+
dynamicTable.Insert(header4.Name, header4.Value);
70+
dynamicTable.Insert(header3.Name, header3.Value);
71+
dynamicTable.Insert(_header2.Name, _header2.Value);
72+
dynamicTable.Insert(_header1.Name, _header1.Value);
73+
74+
VerifyTableEntries(dynamicTable, _header1, _header2);
75+
}
76+
6177
[Fact]
6278
public void ThrowsIndexOutOfRangeException()
6379
{

0 commit comments

Comments
 (0)