Skip to content

Commit 5779de1

Browse files
authored
Merge commit from fork
1 parent bc63e9b commit 5779de1

2 files changed

Lines changed: 40 additions & 10 deletions

File tree

lib/mint/http2.ex

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2438,16 +2438,23 @@ defmodule Mint.HTTP2 do
24382438
conn = put_in(conn.headers_being_processed, nil)
24392439
callback.(conn, responses, hbf, stream)
24402440
else
2441-
new_size = acc_size + byte_size(hbf_chunk)
2442-
conn = assert_header_block_within_max_size(conn, new_size)
2441+
if byte_size(hbf_chunk) == 0 do
2442+
# An empty fragment does not contribute header-block data. Keeping the
2443+
# existing accumulator avoids adding an unbounded number of empty
2444+
# iodata nodes when END_HEADERS is withheld.
2445+
{conn, responses}
2446+
else
2447+
new_size = acc_size + byte_size(hbf_chunk)
2448+
conn = assert_header_block_within_max_size(conn, new_size)
24432449

2444-
conn =
2445-
put_in(
2446-
conn.headers_being_processed,
2447-
{stream_id, [hbf_acc, hbf_chunk], callback, new_size}
2448-
)
2450+
conn =
2451+
put_in(
2452+
conn.headers_being_processed,
2453+
{stream_id, [hbf_acc, hbf_chunk], callback, new_size}
2454+
)
24492455

2450-
{conn, responses}
2456+
{conn, responses}
2457+
end
24512458
end
24522459
end
24532460

@@ -2461,8 +2468,9 @@ defmodule Mint.HTTP2 do
24612468
# CONTINUATION frames is buffered (in compressed form) until END_HEADERS
24622469
# arrives. A server can withhold END_HEADERS and stream CONTINUATION frames
24632470
# indefinitely, so the buffered size is bounded by the locally advertised
2464-
# SETTINGS_MAX_HEADER_LIST_SIZE. The compressed accumulator is never larger
2465-
# than the uncompressed header list it decodes to, so this never rejects a
2471+
# SETTINGS_MAX_HEADER_LIST_SIZE. Empty fragments are not retained in the
2472+
# accumulator. The compressed accumulator is never larger than the
2473+
# uncompressed header list it decodes to, so the size limit never rejects a
24662474
# header block that fits within the advertised limit.
24672475
defp assert_header_block_within_max_size(conn, size) do
24682476
case conn.client_settings.max_header_list_size do

test/mint/http2/conn_test.exs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,28 @@ defmodule Mint.HTTP2Test do
10041004
refute HTTP2.open?(conn)
10051005
end
10061006

1007+
# Regression for GitHub Security Advisory GHSA-8pf6-g464-h6h9.
1008+
test "empty CONTINUATION frames do not grow the header block accumulator", %{conn: conn} do
1009+
{conn, _ref} = open_request(conn)
1010+
1011+
assert_recv_frames [headers(stream_id: stream_id)]
1012+
1013+
empty_continuations =
1014+
List.duplicate(
1015+
continuation(stream_id: stream_id, hbf: "", flags: set_flags(:continuation, [])),
1016+
10_000
1017+
)
1018+
1019+
assert {:ok, %HTTP2{} = conn, []} =
1020+
stream_frames(conn, [
1021+
headers(stream_id: stream_id, hbf: "", flags: set_flags(:headers, []))
1022+
| empty_continuations
1023+
])
1024+
1025+
assert {^stream_id, "", _callback, 0} = conn.headers_being_processed
1026+
assert HTTP2.open?(conn)
1027+
end
1028+
10071029
@tag connect_options: [client_settings: [max_header_list_size: 1_000]]
10081030
test "a single oversized HEADERS fragment past max_header_list_size is a connection error",
10091031
%{conn: conn} do

0 commit comments

Comments
 (0)