Summary
parse_message() extracts the body with a byte-index string slice using the
attacker-controlled Content-Length value. If Content-Length lands in the
middle of a multi-byte UTF-8 sequence, body[..cl] panics, aborting the task.
Location
crates/asterisk-sip/src/parser/mod.rs:793
let body = if let Some(cl) = content_length {
if cl > MAX_CONTENT_LENGTH { return Err(...); }
if cl > 0 && body.len() >= cl {
body[..cl].to_string() // <-- panics if cl is not a char boundary
} else {
body.to_string()
}
} ...
SipMessage::parse first validates the whole datagram as UTF-8, so body is a
valid &str; slicing it on a non-char-boundary byte index is an immediate panic.
Trigger (malformed input)
A single unauthenticated SIP datagram:
INVITE sip:x@h SIP/2.0\r\n
Via: SIP/2.0/UDP h\r\n
Content-Length: 1\r\n
\r\n
é
é is 0xC3 0xA9 (2 bytes). cl = 1, body.len() = 2, so the guard
cl > 0 && body.len() >= cl passes and body[..1] panics:
end byte index 1 is not a char boundary; it is inside 'é' (bytes 0..2 of string)
(Reproduced against the exact expression on master.)
Impact — remote DoS (HIGH)
SipMessage::parse runs in UdpTransport::recv() (transport/mod.rs:144),
which is awaited inline in the single main SIP event loop
(stack.rs:713). The crate builds with the default panic = "unwind", so the
panic unwinds and kills the event-loop task — the entire SIP stack stops
processing signaling from one malformed UDP packet, no auth required. Same
reachability over TCP/TLS/WebSocket transports.
Suggested fix
Slice on a char boundary, e.g. body.get(..cl) and fall back to the full
(already length-bounded) body when cl is not a boundary, or floor cl to the
nearest char boundary. Add a regression test feeding a multi-byte body with a
mid-character Content-Length and asserting no panic.
Summary
parse_message()extracts the body with a byte-index string slice using theattacker-controlled
Content-Lengthvalue. IfContent-Lengthlands in themiddle of a multi-byte UTF-8 sequence,
body[..cl]panics, aborting the task.Location
crates/asterisk-sip/src/parser/mod.rs:793SipMessage::parsefirst validates the whole datagram as UTF-8, sobodyis avalid
&str; slicing it on a non-char-boundary byte index is an immediate panic.Trigger (malformed input)
A single unauthenticated SIP datagram:
éis0xC3 0xA9(2 bytes).cl = 1,body.len() = 2, so the guardcl > 0 && body.len() >= clpasses andbody[..1]panics:(Reproduced against the exact expression on master.)
Impact — remote DoS (HIGH)
SipMessage::parseruns inUdpTransport::recv()(transport/mod.rs:144),which is awaited inline in the single main SIP event loop
(
stack.rs:713). The crate builds with the defaultpanic = "unwind", so thepanic unwinds and kills the event-loop task — the entire SIP stack stops
processing signaling from one malformed UDP packet, no auth required. Same
reachability over TCP/TLS/WebSocket transports.
Suggested fix
Slice on a char boundary, e.g.
body.get(..cl)and fall back to the full(already length-bounded) body when
clis not a boundary, or floorclto thenearest char boundary. Add a regression test feeding a multi-byte body with a
mid-character
Content-Lengthand asserting no panic.