From fb74b85ad41c720c33737d836e9bd0c32586817e Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 6 Oct 2026 09:45:03 +0200 Subject: [PATCH 1/2] Add SockAddr::as_mut_ptr Returns a raw mutable pointer to the address. --- src/sockaddr.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sockaddr.rs b/src/sockaddr.rs index 0b0189a3..e334f7d3 100644 --- a/src/sockaddr.rs +++ b/src/sockaddr.rs @@ -266,6 +266,11 @@ impl SockAddr { &self.storage as *const sockaddr_storage as *const SockAddrStorage } + /// Returns a raw mutable pointer to the address. + pub fn as_mut_ptr(&mut self) -> *mut SockAddrStorage { + &mut self.storage as *mut sockaddr_storage as *mut SockAddrStorage + } + /// Returns the address as the storage. pub const fn as_storage(self) -> SockAddrStorage { SockAddrStorage { From 6e677b0d8a0643616ce7f49b0b9d61a7a649879f Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 6 Oct 2026 10:14:12 +0200 Subject: [PATCH 2/2] Don't use a shared reference in MsgHdrMut Because we used set_msghdr_name, which uses a reference to SockAddr we broke the aliasing rules. See #673 for more details. To fix this use raw pointers instead. Fixes #673 --- src/lib.rs | 37 ++++++++++++++++++++++++++++++++++--- src/sys/unix.rs | 6 +++--- src/sys/windows.rs | 6 +++--- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3d1a75dd..d42f0501 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -622,7 +622,9 @@ impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> { /// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name` /// and `namelen` on Windows. pub fn with_addr(mut self, addr: &'addr SockAddr) -> Self { - sys::set_msghdr_name(&mut self.inner, addr); + // SAFETY: we're casting a const pointer to a mut pointer only to assign + // it, this type doesn't use the pointer mutably. + sys::set_msghdr_name(&mut self.inner, addr.as_ptr().cast_mut(), addr.len()); self } @@ -697,9 +699,8 @@ impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> { /// /// Corresponds to setting `msg_name` and `msg_namelen` on Unix and `name` /// and `namelen` on Windows. - #[allow(clippy::needless_pass_by_ref_mut)] pub fn with_addr(mut self, addr: &'addr mut SockAddr) -> Self { - sys::set_msghdr_name(&mut self.inner, addr); + sys::set_msghdr_name(&mut self.inner, addr.as_mut_ptr(), addr.len()); self } @@ -745,3 +746,33 @@ impl<'name, 'bufs, 'control> fmt::Debug for MsgHdrMut<'name, 'bufs, 'control> { #[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))] unsafe impl Send for MsgHdrMut<'_, '_, '_> {} + +#[test] +#[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))] +fn regression_673() { + // NOTE: ideally this would be moved into the tests directory, but at the + // time of writing Miri doesn't support recvmsg. + + use std::mem::MaybeUninit; + use std::net::{Ipv4Addr, SocketAddrV4}; + + use crate::sys::sockaddr; + use crate::{MaybeUninitSlice, SockAddr}; + + let mut addr = SockAddr::from(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80)); + let mut buf = [MaybeUninit::new(0); 8]; + let mut bufs = [MaybeUninitSlice::new(&mut buf)]; + + let hdr = MsgHdrMut::new() + .with_addr(&mut addr) + .with_buffers(&mut bufs); + + // Mimic what recvmsg(2) does, write to the address. + #[cfg(windows)] + let name = hdr.inner.name as *mut sockaddr; + #[cfg(not(windows))] + let name = hdr.inner.msg_name as *mut sockaddr; + unsafe { (*name).sa_family = 255 }; // Family. + + assert_eq!(addr.family(), 255); +} diff --git a/src/sys/unix.rs b/src/sys/unix.rs index 057a70cf..55f2faa4 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -825,9 +825,9 @@ pub(crate) fn iucv_sockaddr(userid: &str, name: &str) -> io::Result { pub(crate) use libc::msghdr; #[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))] -pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: &SockAddr) { - msg.msg_name = name.as_ptr() as *mut _; - msg.msg_namelen = name.len(); +pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: *mut SockAddrStorage, name_len: socklen_t) { + msg.msg_name = name as *mut _; + msg.msg_namelen = name_len; } #[cfg(not(any(target_os = "redox", target_os = "wasi", target_os = "horizon")))] diff --git a/src/sys/windows.rs b/src/sys/windows.rs index 67de3670..02de234b 100644 --- a/src/sys/windows.rs +++ b/src/sys/windows.rs @@ -250,9 +250,9 @@ impl<'a> MaybeUninitSlice<'a> { // Used in `MsgHdr`. pub(crate) use windows_sys::Win32::Networking::WinSock::WSAMSG as msghdr; -pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: &SockAddr) { - msg.name = name.as_ptr() as *mut _; - msg.namelen = name.len(); +pub(crate) fn set_msghdr_name(msg: &mut msghdr, name: *mut SockAddrStorage, name_len: socklen_t) { + msg.name = name as *mut _; + msg.namelen = name_len; } pub(crate) fn set_msghdr_iov(msg: &mut msghdr, ptr: *mut WSABUF, len: usize) {