Skip to content

fix(quic): refuse a FIN below received stream data - #5906

Merged
kixelated merged 2 commits into
moq-dev:mainfrom
zshenker:fix/quic-final-size-below-received
Oct 19, 2026
Merged

kixelated merged 2 commits into
moq-dev:mainfrom
zshenker:fix/quic-final-size-below-received

Conversation

@zshenker

@zshenker zshenker commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Problem

RFC 9000 section 4.5 requires FINAL_SIZE_ERROR when a STREAM frame's FIN sets a final size below data already received. Recv::ingest only checked a FIN against a final size it already knew, so a first FIN below the high water mark was accepted: the reader got the bytes past it and then blocked forever, because the final size never matched what was read. A peer can stall a reader this way. Tracked by the quest m1/quic/final-size-below-received.

Approach

  • Recv::ingest refuses a FIN whose end is below the stream's high water mark, the check Recv::reset already makes for RESET_STREAM.
  • stream_final_size_below_received is no longer ignored.
  • Closes the quest and records the divergence from quinn under the README's carried changes.

Impact

  • Public API: none.
  • Wire: a peer that shrinks a stream's final size below data it already sent now gets CONNECTION_CLOSE with FINAL_SIZE_ERROR, as RFC 9000 requires, instead of a stalled stream.

Alternatives

None: the RFC requires this error.

Decisions (iterate round 1)

Made unattended with the recommended option:

  • Keep the check additive next to quinn's known-final-size check ✅, rather than folding both into one match self.final_offset(). The fold reads slightly cleaner but rewrites upstream lines, which makes a future quinn sync or an upstream offer harder.
  • Keep the characterization test as the regression test ✅. It fails without the fix (left: None, right: Some(FINAL_SIZE_ERROR)) and passes with it; the harness drives a simulated-time Pair, so no wall clock.

Verification

  • Merged origin/main (one quest-only commit behind).
  • cargo test -p moq-quic --lib final_size: 8 pass; the new test fails with the check disabled.
  • just check: pass.

Follow-ups

(Written by Claude Opus 5.5)

RFC 9000 section 4.5 makes a final size below data already received a
FINAL_SIZE_ERROR. `Recv::ingest` checked a FIN only against a final size
it already knew, so a first FIN below the high water mark was recorded:
the reader got the bytes past it and then blocked forever, since the
final size never matched what was read. Refuse it as `Recv::reset`
already does for RESET_STREAM.

Un-ignores `stream_final_size_below_received` and closes the
m1/quic/final-size-below-received quest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zshenker
zshenker marked this pull request as ready for review October 18, 2026 22:28
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-18T22:29:08.898954Z 4184558 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 32eb8950-c2ad-4311-87ff-98ba6ee188ab
📥 Commits

Reviewing files that changed from the base of the PR and between 8f13d08 and 4184558.

📒 Files selected for processing: 5
  • quest/m1/quic/README.md
  • quest/m1/quic/final-size-below-received.md
  • rs/moq-quic/README.md
  • rs/moq-quic/src/connection/streams/recv.rs
  • rs/moq-quic/src/tests/characterize/frames.rs
💤 Files with no reviewable changes: 3
  • rs/moq-quic/src/tests/characterize/frames.rs
  • quest/m1/quic/final-size-below-received.md
  • quest/m1/quic/README.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

Walkthrough

Recv::ingest now returns FINAL_SIZE_ERROR when a FIN sets a final size below the highest previously received offset. The related characterization test is enabled. The malformed-input README entry now describes this case, and the corresponding quest document and Required list entry are removed.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 41845

FINs that set a final size below already-received stream data now close with FINAL_SIZE_ERROR, as intended. No actionable merge-blocking risk remains in the reviewed change.

Pre-merge checks: Passed 5
Check name Status Explanation
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description clearly explains the RFC requirement, the defect, the implementation, the regression test, and the impact. It directly matches the changeset.
Title check Passed The title is concise, specific, and accurately identifies the primary change: rejecting a FIN below received stream data.
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
✨ Simplify code
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…elow-received

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated added this pull request to the merge queue Oct 19, 2026
Merged via the queue into moq-dev:main with commit fec65d3 Oct 19, 2026
11 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