diff --git a/test/mint/http2/fuzz_test.exs b/test/mint/http2/fuzz_test.exs index 7dbcf74d..79bc5994 100644 --- a/test/mint/http2/fuzz_test.exs +++ b/test/mint/http2/fuzz_test.exs @@ -11,6 +11,7 @@ defmodule Mint.HTTP2.FuzzTest do @recv_timeout 300 @runs String.to_integer(System.get_env("FUZZ_RUNS", "10")) + @initial_window_size 65_535 ## Generators @@ -248,7 +249,7 @@ defmodule Mint.HTTP2.FuzzTest do ) do drain_mailbox() {:ok, port, task} = TestServer.listen_and_accept() - conn = start_connection(port, task, scenario) + {conn, preface_frames} = start_connection(port, task, scenario) {conn, refs, sids, meta} = Enum.reduce(requests, {conn, [], [], %{}}, fn {method, body}, {conn, refs, sids, meta} -> @@ -289,10 +290,11 @@ defmodule Mint.HTTP2.FuzzTest do meta: meta, actions: actions, mode: mode, - window: %{server_view: conn.receive_window_remaining, buffer: "", exact?: true}, + window: %{server_view: @initial_window_size, buffer: "", exact?: true}, log: [] } + state = Enum.reduce(preface_frames, state, &account_client_frame/2) run(conn, actions, state) _ = HTTP2.close(conn) _ = :ssl.close(state.server.socket) @@ -342,8 +344,9 @@ defmodule Mint.HTTP2.FuzzTest do end end - # The server's view of the connection window is the initial window minus the - # DATA payloads it sent plus the WINDOW_UPDATE increments it received. Once + # The server's view of the connection window is the initial 65,535 bytes (RFC + # 9113 6.9.2) minus the DATA payloads it sent plus the WINDOW_UPDATE increments + # it received on stream 0, including the one after the client preface. Once # Mint has processed a segment it must agree with Mint's own view; raw bytes # can swallow later frames into a partial frame, so the check is skipped once # any were sent. @@ -888,7 +891,23 @@ defmodule Mint.HTTP2.FuzzTest do ) {:ok, server_socket} = Task.await(server_socket_task) - :ok = TestServer.perform_http2_handshake(server_socket) + + {:ok, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" <> rest} = + :ssl.recv(server_socket, 0, @recv_timeout) + + # The client preface is a SETTINGS frame, followed by a WINDOW_UPDATE on + # stream 0 when the client raised its connection-level receive window. + {:ok, settings(flags: 0), rest} = Frame.decode_next(rest) + + preface_frames = + case rest do + "" -> + [] + + _ -> + assert {:ok, window_update(stream_id: 0) = frame, ""} = Frame.decode_next(rest) + [frame] + end :ok = :ssl.send(server_socket, [ @@ -909,7 +928,7 @@ defmodule Mint.HTTP2.FuzzTest do {:ok, settings(flags: ^ack_flags, params: []), ""} = Frame.decode_next(data) :ok = :ssl.setopts(server_socket, active: true) Process.put(:fuzz_server, TestServer.new(server_socket)) - conn + {conn, preface_frames} end defp recv_all_frames do