diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 41d30b03a0..e8393d679e 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -766,7 +766,7 @@ impl fmt::Display for SocketAddressLengthNotDynamic { impl std::error::Error for SocketAddressLengthNotDynamic {} impl private::SockaddrLikePriv for () { - fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { + fn as_mut_ptr(_: &mut std::mem::MaybeUninit) -> *mut libc::sockaddr { ptr::null_mut() } } @@ -1451,16 +1451,13 @@ impl PartialEq for SockaddrStorage { pub(super) mod private { pub trait SockaddrLikePriv { - /// Returns a mutable raw pointer to the inner structure. - /// - /// # Safety - /// - /// This method is technically safe, but modifying the inner structure's - /// `family` or `len` fields may result in violating Nix's invariants. - /// It is best to use this method only with foreign functions that do - /// not change the sockaddr type. - fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { - self as *mut Self as *mut libc::sockaddr + fn as_mut_ptr( + s: &mut std::mem::MaybeUninit, + ) -> *mut libc::sockaddr + where + Self: Sized, + { + s.as_mut_ptr().cast() } } } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index a145444fa2..594bf60d9d 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1627,12 +1627,12 @@ impl MultiHeaders { let items = addresses .iter_mut() .enumerate() - .map(|(ix, address)| { + .map(|(ix, mut address)| { let (ptr, cap) = match &mut cmsg_buffers { Some(v) => ((&mut v[ix * msg_controllen] as *mut u8), msg_controllen), None => (std::ptr::null_mut(), 0), }; - let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) }; + let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, &mut address) }; libc::mmsghdr { msg_hdr, msg_len: 0, @@ -1962,17 +1962,25 @@ unsafe fn pack_mhdr_to_receive( iov_buffer_len: usize, cmsg_buffer: *mut u8, cmsg_capacity: usize, - address: *mut S, + address: &mut mem::MaybeUninit, ) -> msghdr where S: SockaddrLike { + let addr_ptr = S::as_mut_ptr(address); + + if !addr_ptr.is_null() { + unsafe { + std::ptr::addr_of_mut!((*addr_ptr).sa_family).write(libc::AF_UNSPEC as _); + } + } + // Musl's msghdr has private fields, so this is the only way to // initialize it. let mut mhdr = mem::MaybeUninit::::zeroed(); let p = mhdr.as_mut_ptr(); unsafe { - (*p).msg_name = address as *mut c_void; + (*p).msg_name = addr_ptr.cast(); (*p).msg_namelen = S::size(); (*p).msg_iov = iov_buffer as *mut iovec; (*p).msg_iovlen = iov_buffer_len as _; @@ -2062,7 +2070,7 @@ pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'i .map(|v| (v.as_mut_ptr(), v.capacity())) .unwrap_or((ptr::null_mut(), 0)); let mut mhdr = unsafe { - pack_mhdr_to_receive(iov.as_mut().as_mut_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr()) + pack_mhdr_to_receive(iov.as_mut().as_mut_ptr(), iov.len(), msg_control, msg_controllen, &mut address) }; let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };