Skip to content

Commit

Permalink
Relax assertions in sockaddr_storage_to_addr to match the documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
khuey committed Aug 10, 2021
1 parent 68488a4 commit 64a507b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
8 changes: 4 additions & 4 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1748,21 +1748,21 @@ pub fn sockaddr_storage_to_addr(
addr: &sockaddr_storage,
len: usize) -> Result<SockAddr> {

assert!(len <= mem::size_of::<sockaddr_un>());
assert!(len <= mem::size_of::<sockaddr_storage>());
if len < mem::size_of_val(&addr.ss_family) {
return Err(Error::from(Errno::ENOTCONN));
}

match c_int::from(addr.ss_family) {
libc::AF_INET => {
assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
assert!(len as usize >= mem::size_of::<sockaddr_in>());
let sin = unsafe {
*(addr as *const sockaddr_storage as *const sockaddr_in)
};
Ok(SockAddr::Inet(InetAddr::V4(sin)))
}
libc::AF_INET6 => {
assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
assert!(len as usize >= mem::size_of::<sockaddr_in6>());
let sin6 = unsafe {
*(addr as *const _ as *const sockaddr_in6)
};
Expand All @@ -1778,10 +1778,10 @@ pub fn sockaddr_storage_to_addr(
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_PACKET => {
use libc::sockaddr_ll;
// Don't assert anything about the size.
// Apparently the Linux kernel can return smaller sizes when
// the value in the last element of sockaddr_ll (`sll_addr`) is
// smaller than the declared size of that field
assert!(len as usize <= mem::size_of::<sockaddr_ll>());
let sll = unsafe {
*(addr as *const _ as *const sockaddr_ll)
};
Expand Down
42 changes: 39 additions & 3 deletions test/sys/test_socket.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::mem::{self, MaybeUninit};
use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
use std::os::unix::io::RawFd;
use std::path::Path;
use std::slice;
use std::str::FromStr;
use libc::c_char;
use libc::{c_char, sockaddr_storage};
#[cfg(any(target_os = "linux", target_os= "android"))]
use crate::*;

#[test]
pub fn test_inetv4_addr_to_sock_addr() {
let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
let addr = InetAddr::from_std(&actual);
let sockaddr = SockAddr::new_inet(addr);

match addr {
InetAddr::V4(addr) => {
Expand All @@ -31,6 +33,22 @@ pub fn test_inetv4_addr_to_sock_addr() {

let inet = addr.to_std();
assert_eq!(actual, inet);

let (storage, ffi_size) = {
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>();
let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
unsafe {
storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1);
(storage.assume_init(), ffi_size)
}
};

let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
assert_eq!(from_storage, sockaddr);
let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
assert_eq!(from_storage, sockaddr);
}

#[test]
Expand All @@ -42,6 +60,7 @@ pub fn test_inetv6_addr_to_sock_addr() {

let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
let addr = InetAddr::from_std(&actual);
let sockaddr = SockAddr::new_inet(addr);

match addr {
InetAddr::V6(addr) => {
Expand All @@ -53,6 +72,24 @@ pub fn test_inetv6_addr_to_sock_addr() {
}

assert_eq!(actual, addr.to_std());

let (storage, ffi_size) = {
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>();
let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
// XXX this does not pass.
// assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize);
unsafe {
storage_ptr.copy_from_nonoverlapping((ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(), 1);
(storage.assume_init(), ffi_size)
}
};

let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
assert_eq!(from_storage, sockaddr);
let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
assert_eq!(from_storage, sockaddr);
}

#[test]
Expand Down Expand Up @@ -1169,7 +1206,6 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
use std::io;
use std::io::Write;
use nix::ifaddrs::getifaddrs;
use nix::sys::socket::SockAddr;
use nix::net::if_::*;

let addrs = match getifaddrs() {
Expand Down

0 comments on commit 64a507b

Please sign in to comment.