Skip to content

Commit

Permalink
For invalid IP address conversions with future Rust versions
Browse files Browse the repository at this point in the history
Rust's standard library no longer guarantees that Ipv4Addr and Ipv6Addr
are wrappers around the C types (though for now at least, they are
identical on all platforms I'm aware of).  So do the conversions
explicitly instead of transmuting.

Fixes #2053
  • Loading branch information
asomers committed Jun 28, 2023
1 parent 9a3010b commit 1546857
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ This project adheres to [Semantic Versioning](https://semver.org/).
([#1964](https://github.com/nix-rust/nix/pull/1964))
- Fix: send ETH_P_ALL in htons format
([#1925](https://github.com/nix-rust/nix/pull/1925))
- Fix potentially invalid conversions in
`SockaddrIn::from<std::net::SocketAddrV4>`,
`SockaddrIn6::from<std::net::SockaddrV6>`, `IpMembershipRequest::new`, and
`Ipv6MembershipRequest::new` with future Rust versions.
([#2061](https://github.com/nix-rust/nix/pull/2061))

### Removed

Expand Down
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ libc = { version = "0.2.141", features = ["extra_traits"] }
bitflags = "1.1"
cfg-if = "1.0"
pin-utils = { version = "0.1.0", optional = true }
static_assertions = "1"
memoffset = { version = "0.9", optional = true }

[features]
Expand Down
16 changes: 6 additions & 10 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,17 @@ use std::{fmt, mem, net, ptr, slice};
/// 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) }
libc::in_addr {
s_addr: u32::from_ne_bytes(addr.octets())
}
}

/// 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) }
libc::in6_addr {
s6_addr: addr.octets()
}
}

/// These constants specify the protocol family to be used
Expand Down Expand Up @@ -949,9 +948,6 @@ impl SockaddrLike for () {
}

/// An IPv4 socket address
// This is identical to net::SocketAddrV4. But the standard library
// doesn't allow direct access to the libc fields, which we need. So we
// reimplement it here.
#[cfg(feature = "net")]
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
Expand Down

0 comments on commit 1546857

Please sign in to comment.