diff --git a/lib/mint/http2.ex b/lib/mint/http2.ex index 31f3c5e4..b3aaea74 100644 --- a/lib/mint/http2.ex +++ b/lib/mint/http2.ex @@ -2210,19 +2210,15 @@ defmodule Mint.HTTP2 do # 32 bytes per field. The compressed block is bounded while it is accumulated, # but indexed fields decode to far more bytes than they take on the wire. defp header_list_size_error(conn, headers) do - case conn.client_settings.max_header_list_size do - :infinity -> - nil - - max_size -> - # TODO: replace with Enum.sum_by when we depend on 1.18+ - size = - Enum.reduce(headers, 0, fn {name, value}, acc -> - acc + byte_size(name) + byte_size(value) + 32 - end) + max_size = conn.client_settings.max_header_list_size - if size > max_size, do: {:max_header_list_size_exceeded, size, max_size} - end + # TODO: replace with Enum.sum_by when we depend on 1.18+ + size = + Enum.reduce(headers, 0, fn {name, value}, acc -> + acc + byte_size(name) + byte_size(value) + 32 + end) + + if size > max_size, do: {:max_header_list_size_exceeded, size, max_size} end # RFC 9113 5.1: HEADERS frames move a stream reserved by a PUSH_PROMISE to the @@ -3089,22 +3085,17 @@ defmodule Mint.HTTP2 do @max_dynamic_table_size_updates_size 2 * 6 defp assert_header_block_within_max_size(conn, size) do - case conn.client_settings.max_header_list_size do - :infinity -> - conn - - max_size -> - max_block_size = div(max_size * 30, 8) + @max_dynamic_table_size_updates_size + max_size = conn.client_settings.max_header_list_size + max_block_size = div(max_size * 30, 8) + @max_dynamic_table_size_updates_size - if size > max_block_size do - debug_data = - "header block fragments exceed #{max_block_size} bytes, the bound for " <> - "SETTINGS_MAX_HEADER_LIST_SIZE of #{max_size} bytes" + if size > max_block_size do + debug_data = + "header block fragments exceed #{max_block_size} bytes, the bound for " <> + "SETTINGS_MAX_HEADER_LIST_SIZE of #{max_size} bytes" - send_connection_error!(conn, :protocol_error, debug_data) - else - conn - end + send_connection_error!(conn, :protocol_error, debug_data) + else + conn end end diff --git a/test/mint/http2/conn_test.exs b/test/mint/http2/conn_test.exs index f4f4647b..60ae7542 100644 --- a/test/mint/http2/conn_test.exs +++ b/test/mint/http2/conn_test.exs @@ -313,6 +313,18 @@ defmodule Mint.HTTP2Test do end end + test "raises an error if the client :max_header_list_size setting is :infinity", + %{server_port: port} do + message = ":max_header_list_size must be an integer, got: :infinity" + + assert_raise ArgumentError, message, fn -> + HTTP2.connect(:https, "localhost", port, + client_settings: [max_header_list_size: :infinity], + transport_opts: [verify: :verify_none] + ) + end + end + test "closes the transport socket if anything goes wrong during the setup", %{server_port: port} do {:ok, socket} = :ssl.connect(~c"localhost", port, verify: :verify_none) @@ -4070,6 +4082,10 @@ defmodule Mint.HTTP2Test do HTTP2.put_settings(conn, header_table_size: :oops) end + assert_raise ArgumentError, ~r/:max_header_list_size must be an integer/, fn -> + HTTP2.put_settings(conn, max_header_list_size: :infinity) + end + assert_raise ArgumentError, "unknown setting parameter :oops", fn -> HTTP2.put_settings(conn, oops: 1) end