Skip to content

Commit f582bc8

Browse files
committed
fix(udp/fast-apple): ignore empty cmsghdr
On MacOS < 14, with `fast-apple-datapath` feature, calls to `libc::CMSG_NXTHDR` might continuously return empty (i.e. all zero) `libc::cmsghdr` instead of a null pointer. This results in a busy loop in `decode_recv`: ``` rust let cmsg_iter = unsafe { cmsg::Iter::new(hdr) }; for cmsg in cmsg_iter { match (cmsg.cmsg_level, cmsg.cmsg_type) { ``` https://github.com/quinn-rs/quinn/blob/b4378bb39dab4b58a1e6a3fea4fff9f87033dab6/quinn-udp/src/unix.rs#L685C1-L687C50 This commit fixes the above, returning a `null_mut()` pointer on an empty `libc::cmsgdhr`, thus terminating the `cmsg_iter`. See also mozilla/neqo#2427 for details.
1 parent b4378bb commit f582bc8

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

quinn-udp/src/cmsg/unix.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,18 @@ impl MsgHdr for crate::imp::msghdr_x {
4343

4444
fn cmsg_nxt_hdr(&self, cmsg: &Self::ControlMessage) -> *mut Self::ControlMessage {
4545
let selfp = self as *const _ as *mut libc::msghdr;
46-
unsafe { libc::CMSG_NXTHDR(selfp, cmsg) }
46+
let next = unsafe { libc::CMSG_NXTHDR(selfp, cmsg) };
47+
48+
// On MacOS < 14 CMSG_NXTHDR might continuously return a zeroed cmsg. In
49+
// such case, return a null pointer instead, thus indicating the end of
50+
// the cmsghdr chain.
51+
if unsafe { next.as_ref() }
52+
.is_some_and(|n| (n.cmsg_len as usize) < std::mem::size_of::<libc::cmsghdr>())
53+
{
54+
return std::ptr::null_mut();
55+
}
56+
57+
next
4758
}
4859

4960
fn set_control_len(&mut self, len: usize) {

0 commit comments

Comments
 (0)