Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions test/mint/http2/fuzz_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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} ->
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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, [
Expand All @@ -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
Expand Down
Loading