Reject malformed Connect END_STREAM JSON#192
Merged
iainmcgin merged 2 commits intoJun 28, 2026
Merged
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
Contributor
Author
|
I have read the CLA Document and I hereby sign the CLA |
The metadata_to_trailers helper extracted in this branch contained the pre-anthropics#169 uncapped HeaderMap::append loop, which panics once the map reaches its 32k-entry hard ceiling — a server can hit that with a few hundred KB of END_STREAM JSON. main replaced both call sites with append_metadata_capped (try_append + stop at the cap) in anthropics#169; keep that, drop the helper. Also drops the now-dead Default derive on ClientEndStreamResponse (existed only for the removed unwrap_or_default()) and adds the CHANGELOG entry alongside its anthropics#163/anthropics#168 siblings.
iainmcgin
approved these changes
Jun 28, 2026
iainmcgin
left a comment
Collaborator
There was a problem hiding this comment.
[claude code] Thanks — the fix is correct and the regression tests are well-targeted. I pushed one maintainer commit (d55d2da) that merges main and resolves the conflict in client/mod.rs:
- Dropped
metadata_to_trailersand keptmain'sappend_metadata_cappedat both call sites. The extracted helper carried the pre-#169 uncappedHeaderMap::appendloop, which panics at the map's ~32k-entry ceiling — a server can hit that with a few hundred KB of END_STREAM JSON. #169 replaced both sites withtry_append-and-stop; the resolution preserves that guard while keeping yourparse_connect_end_stream/end_stream_error_to_connect_errorextractions. - Removed the
Defaultderive onClientEndStreamResponse— it existed only for theunwrap_or_default()this PR removes, and leaving it would let a future.unwrap_or_default()compile and silently reintroduce the bug. - Added a
CHANGELOG.mdentry under[Unreleased] / Fixedalongside its #163/#168 siblings, plus doc comments on the two new helpers.
One pre-existing asymmetry surfaced during review (not a regression here, so not addressed in this PR): the server-stream parse-error path at process_end_stream doesn't attach self.headers to the returned ConnectError, while the client-stream path does. Worth a follow-up to make them uniform.
LGTM with the above applied.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
The client used
serde_json::from_slice(...).unwrap_or_default()when parsing Connect END_STREAM payloads. Invalid JSON therefore became the default successful end-stream shape, so a malformed protocol terminator could be reported as a clean RPC completion.Testing
cargo test -p connectrpc malformed_end_stream_jsoncargo test -p connectrpccargo test --workspacecargo check -p connectrpc --no-default-featurescargo clippy -p connectrpc --all-targets --all-features -- -D warningsgit diff --check