-
Notifications
You must be signed in to change notification settings - Fork 702
Description
The functions ipv4addr_to_libc
and ipv6addr_to_libc
transmute from std::net::Ipv4Addr
to libc::in_addr
, but this is unsound.
Lines 39 to 54 in 89b4976
/// Convert a std::net::Ipv4Addr into the libc form. | |
#[cfg(feature = "net")] | |
pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr { | |
static_assertions::assert_eq_size!(net::Ipv4Addr, libc::in_addr); | |
// Safe because both types have the same memory layout, and no fancy Drop | |
// impls. | |
unsafe { mem::transmute(addr) } | |
} | |
/// Convert a std::net::Ipv6Addr into the libc form. | |
#[cfg(feature = "net")] | |
pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr { | |
static_assertions::assert_eq_size!(net::Ipv6Addr, libc::in6_addr); | |
// Safe because both are Newtype wrappers around the same libc type | |
unsafe { mem::transmute(*addr) } | |
} |
The rust socket address types do not have the same layouts as their corresponding libc types, even if their size is the same.
See rust-lang/rust#78802 for details.
This release changes the memory layout of
Ipv4Addr
,Ipv6Addr
,SocketAddrV4
andSocketAddrV6
. The standard library no longer implements these as the corresponding libc structs (sockaddr_in
,sockaddr_in6
etc.). This internal representation was never exposed, but some crates relied on it anyway by unsafely transmuting. This change will cause those crates to make invalid memory accesses.
This change obviously changes the memory layout of the types. And it turns out some libraries invalidly assumes the memory layout and does very dangerous pointer casts to convert them. These libraries will have undefined behaviour and perform invalid memory access until patched.