Skip to content

harden(sip-transport): cap stream body at Content-Length before buffering (#115) - #119

Merged
ryanmurf merged 1 commit into
masterfrom
hardening/proto-tcp-body-cap
Jul 17, 2026
Merged

harden(sip-transport): cap stream body at Content-Length before buffering (#115)#119
ryanmurf merged 1 commit into
masterfrom
hardening/proto-tcp-body-cap

Conversation

@ryanmurf

Copy link
Copy Markdown
Owner

Fixes #115TcpTransport::read_from_stream read a peer-declared Content-Length number of bytes into its buffer with no upper bound, allowing unbounded buffer growth (and a latent usize overflow in body_start + content_length). The UDP path is already bounded by the parser MAX_CONTENT_LENGTH; the stream path was not.

Fix

Reject a declared Content-Length above MAX_STREAM_BODY_LENGTH (65536, matching the parser) as soon as the headers are in — before allocating for, or awaiting, the body.

Test + RED control

tcp_rejects_oversized_content_length_without_buffering_body: a peer declares an over-cap body, sends a few bytes, and holds the connection open. With the cap, accept() returns Err(Parse) promptly; without it, the body-read loop blocks forever waiting for the declared length that never arrives. RED run with the cap reverted:

tcp_rejects_oversized_content_length_without_buffering_body ... FAILED
  panicked at transport/mod.rs:591:9
  'accept() must resolve promptly (reject on headers), not block on the body'
  (test timed out after 2s)

With the fix applied: transport tests 35 passed; full cargo test --workspace --exclude pjsip-shim green; cargo clippy --workspace --exclude pjsip-shim -- -D warnings clean. Toolchain 1.97.0.

🤖 Generated with Claude Code

…ring

`TcpTransport::read_from_stream` read `Content-Length` bytes into its buffer
with no upper bound. A stream peer could declare an arbitrarily large body and
drive unbounded buffer growth (and `body_start + content_length` could
overflow `usize`) — a memory-exhaustion DoS. The UDP path already bounds this
via the parser's MAX_CONTENT_LENGTH; the stream path did not.

Reject a declared Content-Length above MAX_STREAM_BODY_LENGTH (65536, matching
the parser) as soon as the headers are in, before waiting for or allocating the
body.

Regression test: a peer declares an over-cap body, sends a few bytes, and holds
the connection open. With the cap, accept() returns Err promptly; without it,
the body-read loop blocks forever, so the test times out (verified RED).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XH6jhrG4ZCL8xfCktK4Zms
@ryanmurf
ryanmurf merged commit e225f08 into master Jul 17, 2026
3 checks passed
@ryanmurf
ryanmurf deleted the hardening/proto-tcp-body-cap branch July 17, 2026 00:46
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.

DoS: TCP transport buffers Content-Length bytes with no upper bound (memory exhaustion)

1 participant