Repository navigation
fix(common): reject malformed user headers during deserialization - #4670
udaya-arka wants to merge 7 commits into
Conversation
|
Thanks for the PR. It is labeled If AI was used to create this PR, you must run the Slash commands (own line, regular comment) move it around the queue:
See CONTRIBUTING.md for details. |
|
Thanks @udaya-arka, and welcome. Routing the JSON through The CI runs show "action required" because a maintainer has to approve workflows for a first-time contributor, so they will start once someone approves them. One small thing: |
Serde's derived Deserialize for HeaderField<T> bypassed the length and fixed-size checks enforced by constructors (1..=255 bytes, exact width for fixed kinds). This allowed malformed typed user headers on the HTTP produce endpoint to be encoded into the wire format under the assumption that HeaderField instances are valid by construction, corrupting headers for readers. Implement custom Deserialize for HeaderField<T> routing decoded bytes through from_raw(), returning InvalidHeaderKey for keys and InvalidHeaderValue for values via a sealed HeaderFieldMarker trait. Add a debug_assert! in user_headers_to_wire to assert TLV validity on encode. Signed-off-by: Prabhath Nampally <prabhathn03@gmail.com>
Signed-off-by: Prabhath Nampally <prabhathn03@gmail.com>
504fc06 to
26fb845
Compare
|
Hi @justinmclean, I'm happy to contribute, and thanks for pointing out the redundant I've removed it in a new commit. I've also signed off my previous commit using an interactive rebase, so the commit hashes may have changed. |
|
/skill team-review |
There was a problem hiding this comment.
Summary: The header validation matches the binary codec, and the raw base64 header form stays opaque by design. The Rust build and tests are still queued, so this review rests on source reading and flags an extra copy per decoded header field, a new IggyMessage test that cannot fail, and a key error code that differs between from_raw and TryFrom.
Counts: critical 0, warning 3, nit 0, simplification 1
Findings without an anchor on a changed line:
core/common/src/wire_conversions.rssimplification:headers_from_validated_slice()re-checksexpected_sizeand builds fields withnew_unchecked(), duplicating whatfrom_raw()now enforces with the same error codes. Build each field withHeaderKey::from_raw()andHeaderValue::from_raw().
This review was generated by Claude Code 2.1.310 on deepseek-flash[1m]. Review the output before you act on it.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4670 +/- ##
=============================================
- Coverage 80.72% 70.48% -10.25%
- Complexity 3104 3106 +2
=============================================
Files 1479 1477 -2
Lines 361399 353961 -7438
Branches 305269 297832 -7437
=============================================
- Hits 291746 249473 -42273
- Misses 62771 97309 +34538
- Partials 6882 7179 +297
🚀 New features to boost your workflow:
|
- Avoid extra allocation in HeaderField::deserialize by moving owned Bytes into from_raw_bytes() - Bound FromStr and TryFrom for HeaderField by HeaderFieldMarker to return InvalidHeaderKey for keys - Fix IggyMessage test payload to include the required header object and verify valid headers deserialize Signed-off-by: Prabhath Nampally <prabhathn03@gmail.com>
|
/ready |
Simplify headers_from_validated_slice() by delegating field validation and construction to HeaderKey::from_raw() and HeaderValue::from_raw(), removing duplicated expected_size checks and new_unchecked() calls. Signed-off-by: Prabhath Nampally <prabhathn03@gmail.com>
|
performed refactoring in /ready |
Which issue does this PR address?
Closes #4604
Rationale
The HTTP produce endpoint accepted typed user headers that violate the wire protocol's TLV bounds (0-byte values, widths mismatched with fixed-size types like
int32, or values > 255 bytes). When encoded byuser_headers_to_wire, these headers corrupted the message TLV stream, causing consumers polling the message to fail header decoding (Err(InvalidHeaderValue)) or silently drop all headers on the message (Ok(None)).What changed?
HeaderFieldMarkertrait onKeyMarkerandValueMarkerreturningIggyError::InvalidHeaderKeyandIggyError::InvalidHeaderValuerespectively.HeaderField<T>::from_rawbyT: HeaderFieldMarker, returning the marker-specific error on empty fields, lengths > 255 bytes, or fixed-kind width mismatches.DeserializeforHeaderField<T>that deserializes raw base64 data and routes it throughSelf::from_raw(), rejecting malformed keys/values at the HTTP/JSON boundary (HTTP 400).debug_assert!inuser_headers_to_wireverifying that the encoded buffer is structurally valid TLV.send_messages.rs, and added unit tests forHeaderField,HeaderEntry,HeaderKey,HeaderValue, andIggyMessagedeserialization.Local Execution
cargo test -p iggy_commoncargo test -p iggycargo test -p iggy-clicargo clippy --package iggy_common --all-targetscargo fmt --check --package iggy_commonAI Usage