Skip to content

net.http: fix four h2 server correctness gaps found in #27435 review#27469

Merged
JalonSolov merged 2 commits into
vlang:masterfrom
quaesitor-scientiam:fix-h2-server-post-27435
Jun 18, 2026
Merged

net.http: fix four h2 server correctness gaps found in #27435 review#27469
JalonSolov merged 2 commits into
vlang:masterfrom
quaesitor-scientiam:fix-h2-server-post-27435

Conversation

@quaesitor-scientiam

Copy link
Copy Markdown
Contributor

Four correctness fixes identified during code review of #27435 (merged) but
not included before merge.

1. apply_settings overflow guard (RFC 7540 §6.5.3)

SETTINGS_INITIAL_WINDOW_SIZE values above 2^31−1 must be rejected as
FLOW_CONTROL_ERROR; previously they were stored unchecked, inflating every
active stream's send-window to ~4 GB. apply_settings now returns ! and
validates the value before applying the delta to open streams.

2. Double unmark_idle race on fd recycling (handle_conn)

handle_conn's outer defer unconditionally called unmark_idle after
serve_h2_conn_with_idle_tracker returned, but serve() already owns the
mark_idle/unmark_idle lifetime for the connection. After serve()'s
defer fires, the OS can recycle the fd number for a new connection that
has already called mark_idle; the stale unmark then silently evicts the
new connection from the tracker, preventing close_idle from shutting it
down and leaking its reader goroutine.

Fix: track is_h2 in handle_conn and skip the outer unmark on the H2
path.

3. serve() write-truncation comment

The comment said shutdown interrupts "an h2 request in flight", implying
only the frame-read side. Added an explicit note that response writes may
also be truncated mid-DATA-frame, since the connection handle stays
registered with TlsIdleConnTracker for the connection's entire lifetime
(the whole point of #27435).

4. Extract handle_control_frame — eliminate dispatch/pump duplication

SETTINGS, PING, and WINDOW_UPDATE handling was copy-pasted verbatim
in both dispatch_frame and pump_for_window. Finding 1's change to
apply_settings (! return) would not have propagated to
pump_for_window automatically; now both call the same
handle_control_frame helper and any future change propagates to both
callers automatically.

Verification

vlib/net/http/h2_server_test.v passes (GCC; TCC fails unrelated to these
changes due to stale mbedtls threading objects from #27437).

Fixes items identified in the review of #27435.

🤖 Generated with Claude Code

…view

1. apply_settings overflow guard (RFC 7540 §6.5.3)
   SETTINGS_INITIAL_WINDOW_SIZE values above 2^31-1 must be rejected as
   FLOW_CONTROL_ERROR; previously they were stored unchecked, inflating
   every active stream send-window to ~4 GB. apply_settings now returns !
   and validates the new value before applying the delta.

2. Double unmark_idle race on fd recycling (handle_conn)
   handle_conn's outer defer unconditionally called unmark_idle after
   serve_h2_conn_with_idle_tracker returned, but serve() already owns
   mark_idle/unmark_idle for the connection lifetime. After serve()'s defer
   fires, the OS can recycle the fd; the stale unmark then evicts the new
   connection from the tracker, preventing close_idle from shutting it down.
   Fixed by tracking is_h2 and skipping the outer unmark on the H2 path.

3. close_idle write truncation comment
   Update serve()'s comment to note that response writes, not just frame
   reads, may be truncated mid-DATA-frame on shutdown.

4. Extract handle_control_frame to deduplicate dispatch_frame/pump_for_window
   SETTINGS, PING, and WINDOW_UPDATE handling was copy-pasted verbatim in
   both functions. Any fix to apply_settings (e.g. finding 1) would not
   automatically propagate to pump_for_window. Extracted into a shared
   handle_control_frame helper called from both dispatch sites.

Co-Authored-By: WOZCODE <contact@withwoz.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22d335a6f7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread vlib/net/http/h2_server.v
…erver

Three RFC 7540 correctness fixes in H2ServerConn:

- apply_settings: send FLOW_CONTROL_ERROR (not PROTOCOL_ERROR) before
  returning when SETTINGS_INITIAL_WINDOW_SIZE exceeds 2^31-1 (S6.5.3).
  send_goaway now sets closing=true so the outer handler skips the
  duplicate PROTOCOL_ERROR GOAWAY.

- apply_settings: validate SETTINGS_MAX_FRAME_SIZE is in [16384,
  16777215] (S6.5.2) before storing it. An out-of-range value was
  previously stored and could cause an infinite loop in send_body /
  send_header_block if the peer set it to 0.

- send_goaway: set closing=true after a successful frame write so that
  serve_h2_conn_with_idle_tracker can skip the redundant PROTOCOL_ERROR
  GOAWAY it previously always sent.

Co-Authored-By: WOZCODE <contact@withwoz.com>
@JalonSolov

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 18370bdb7b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@JalonSolov JalonSolov merged commit 677eade into vlang:master Jun 18, 2026
67 of 83 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants