Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 44 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,10 @@ 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.
let len = addr.len(); // Get length first to not invalidate raw pointer.
sys::set_msghdr_name(&mut self.inner, addr.as_ptr().cast_mut(), len);
self
}

Expand All @@ -631,8 +634,9 @@ impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
/// and `dwBufferCount` on Windows.
pub fn with_buffers(mut self, bufs: &'bufs [IoSlice<'_>]) -> Self {
let len = bufs.len(); // Get length first to not invalidate raw pointer.
let ptr = bufs.as_ptr() as *mut _;
sys::set_msghdr_iov(&mut self.inner, ptr, bufs.len());
sys::set_msghdr_iov(&mut self.inner, ptr, len);
self
}

Expand All @@ -641,8 +645,9 @@ impl<'addr, 'bufs, 'control> MsgHdr<'addr, 'bufs, 'control> {
/// Corresponds to setting `msg_control` and `msg_controllen` on Unix and
/// `Control` on Windows.
pub fn with_control(mut self, buf: &'control [u8]) -> Self {
let len = buf.len(); // Get length first to not invalidate raw pointer.
let ptr = buf.as_ptr() as *mut _;
sys::set_msghdr_control(&mut self.inner, ptr, buf.len());
sys::set_msghdr_control(&mut self.inner, ptr, len);
self
}

Expand Down Expand Up @@ -697,9 +702,9 @@ 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);
let len = addr.len(); // Get length first to not invalidate raw pointer.
sys::set_msghdr_name(&mut self.inner, addr.as_mut_ptr(), len);
self
}

Expand All @@ -708,7 +713,8 @@ impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
/// Corresponds to setting `msg_iov` and `msg_iovlen` on Unix and `lpBuffers`
/// and `dwBufferCount` on Windows.
pub fn with_buffers(mut self, bufs: &'bufs mut [MaybeUninitSlice<'_>]) -> Self {
sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), bufs.len());
let len = bufs.len(); // Get length first to not invalidate raw pointer.
sys::set_msghdr_iov(&mut self.inner, bufs.as_mut_ptr().cast(), len);
self
}

Expand All @@ -717,7 +723,8 @@ impl<'addr, 'bufs, 'control> MsgHdrMut<'addr, 'bufs, 'control> {
/// Corresponds to setting `msg_control` and `msg_controllen` on Unix and
/// `Control` on Windows.
pub fn with_control(mut self, buf: &'control mut [MaybeUninit<u8>]) -> Self {
sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), buf.len());
let len = buf.len(); // Get length first to not invalidate raw pointer.
sys::set_msghdr_control(&mut self.inner, buf.as_mut_ptr().cast(), len);
self
}

Expand Down Expand Up @@ -745,3 +752,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);
}
5 changes: 5 additions & 0 deletions src/sockaddr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
&mut self.storage as *mut sockaddr_storage as *mut SockAddrStorage
&raw mut self.storage as *mut SockAddrStorage

or if this doesn't work on MSRV:

Suggested change
&mut self.storage as *mut sockaddr_storage as *mut SockAddrStorage
addr_of_mut!(self.storage) as *mut SockAddrStorage

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried the nicer way, but the MSRV is too low. The code matches the as_ptr function.

}

/// Returns the address as the storage.
pub const fn as_storage(self) -> SockAddrStorage {
SockAddrStorage {
Expand Down
6 changes: 3 additions & 3 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,9 +825,9 @@ pub(crate) fn iucv_sockaddr(userid: &str, name: &str) -> io::Result<SockAddr> {
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")))]
Expand Down
6 changes: 3 additions & 3 deletions src/sys/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading