Summary
TcpConnectionManager::read_from_stream frames a SIP message using the
Content-Length header, but (1) the length is parsed as an unbounded usize
and added to the body offset without overflow protection, and (2) the body-read
loop has no size cap, so a large Content-Length drives unbounded buffering.
Location
crates/asterisk-sip/src/transport/mod.rs:351-364
let content_length = extract_content_length(header_text); // unbounded usize
let body_start = sep_pos + 4;
let total_needed = body_start + content_length; // (1) can overflow
while buf.len() < total_needed { // (2) no 65535 cap here
let n = stream.read(&mut temp).await?;
if n == 0 { break; }
buf.extend_from_slice(&temp[..n]);
}
extract_content_length (:431) parses the raw value with no upper bound.
Impact
body_start + content_length overflows for Content-Length near
usize::MAX: panic in debug (arithmetic overflow), wraps in release.
- The 65535 cap exists only in the outer header-read loop (
:368), not the
inner body loop, so Content-Length: 4000000000 (dribbled) forces the
connection to buffer gigabytes → memory-exhaustion DoS. The
MAX_CONTENT_LENGTH check in parse_message runs only after the buffer is
already filled, so it does not bound this.
Suggested fix (low-risk)
Reject content_length > MAX_CONTENT_LENGTH (65536) immediately after
extraction, and use saturating_add/checked_add for total_needed. Filed
rather than fixed here because a red-capable regression test needs TCP socket
plumbing; recommend pairing the fix with a small framing-math helper that is
unit-testable.
Summary
TcpConnectionManager::read_from_streamframes a SIP message using theContent-Lengthheader, but (1) the length is parsed as an unboundedusizeand added to the body offset without overflow protection, and (2) the body-read
loop has no size cap, so a large
Content-Lengthdrives unbounded buffering.Location
crates/asterisk-sip/src/transport/mod.rs:351-364extract_content_length(:431) parses the raw value with no upper bound.Impact
body_start + content_lengthoverflows forContent-Lengthnearusize::MAX: panic in debug (arithmetic overflow), wraps in release.:368), not theinner body loop, so
Content-Length: 4000000000(dribbled) forces theconnection to buffer gigabytes → memory-exhaustion DoS. The
MAX_CONTENT_LENGTHcheck inparse_messageruns only after the buffer isalready filled, so it does not bound this.
Suggested fix (low-risk)
Reject
content_length > MAX_CONTENT_LENGTH(65536) immediately afterextraction, and use
saturating_add/checked_addfortotal_needed. Filedrather than fixed here because a red-capable regression test needs TCP socket
plumbing; recommend pairing the fix with a small framing-math helper that is
unit-testable.