Skip to content

Commit

Permalink
Definition of the SockaddrFromRaw trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan561 committed Nov 29, 2023
1 parent 39ad47b commit e079841
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog/2235.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added the `SockaddrFromRaw` trait.
56 changes: 56 additions & 0 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,14 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
}
}

/// Checked conversion from a socket address pointer.
///
/// **Note**: This trait is [sealed] and its functionality is hidden.
/// It cannot be implemented outside of nix.
///
/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
pub trait SockaddrFromRaw: private::SockaddrFromRawPriv {}

/// The error returned by [`SockaddrLike::set_length`] on an address whose length is statically
/// fixed.
#[derive(Copy, Clone, Debug)]
Expand Down Expand Up @@ -1450,6 +1458,8 @@ impl PartialEq for SockaddrStorage {
}

pub(super) mod private {
use std::mem::MaybeUninit;

pub trait SockaddrLikePriv {
/// Returns a mutable raw pointer to the inner structure.
///
Expand All @@ -1463,6 +1473,52 @@ pub(super) mod private {
self as *mut Self as *mut libc::sockaddr
}
}

/// Checked conversion from a socket address pointer.
pub trait SockaddrFromRawPriv {
/// The libc storage type for this socket address.
type Storage: Copy + Send + Sync + 'static;

/// Unsafe constructor from a variable length source.
///
/// **Note**: This method must run the invalidity checks setuped by [`Self::init_storage`]. For these checks,
/// it must only access the fields that have been initialized by [`Self::init_storage`], the other fields
/// could be uninitialized.
///
/// **Note**: Implementors should not forget that `len` can be larger than the size of
/// `Self::Storage`, so usually a bounds check on the passed length of the
/// address is mandatory, too.
///
/// # Safety
///
/// One of the following must be true:
///
/// - `addr` must be dereferencable to `Self::Storage`.
///
/// - `addr` has been initialized with `Self::init_storage`.
///
/// - `addr` has been zeroed.
///
/// Additionally, if `addr` is dereferencable to `Self::Storage`, then `len` must indicate
/// the actual length of the address.
unsafe fn from_raw(
addr: *const Self::Storage,
len: usize,
) -> Self
where
Self: Sized;

/// Initialize the storage for this socket address, such that after calling this function,
/// the memory representation of the argument is either valid or *provably* invalid for `Self`.
///
/// Provably means that the invalidity must be detectable by only reading fields that have been
/// initialized by this function.
fn init_storage(buf: &mut MaybeUninit<Self::Storage>) {
unsafe {
buf.as_mut_ptr().write_bytes(0u8, 1);
}
}
}
}

#[cfg(linux_android)]
Expand Down
2 changes: 1 addition & 1 deletion src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub mod sockopt;
*
*/

pub use self::addr::{SockaddrLike, SockaddrStorage};
pub use self::addr::{SockaddrFromRaw, SockaddrLike, SockaddrStorage};

#[cfg(solarish)]
pub use self::addr::{AddressFamily, UnixAddr};
Expand Down

0 comments on commit e079841

Please sign in to comment.