Skip to content

Commit 64a507b

Browse files
committed
Relax assertions in sockaddr_storage_to_addr to match the documentation.
Fixes #1479
1 parent 68488a4 commit 64a507b

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

src/sys/socket/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,21 +1748,21 @@ pub fn sockaddr_storage_to_addr(
17481748
addr: &sockaddr_storage,
17491749
len: usize) -> Result<SockAddr> {
17501750

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

17561756
match c_int::from(addr.ss_family) {
17571757
libc::AF_INET => {
1758-
assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
1758+
assert!(len as usize >= mem::size_of::<sockaddr_in>());
17591759
let sin = unsafe {
17601760
*(addr as *const sockaddr_storage as *const sockaddr_in)
17611761
};
17621762
Ok(SockAddr::Inet(InetAddr::V4(sin)))
17631763
}
17641764
libc::AF_INET6 => {
1765-
assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
1765+
assert!(len as usize >= mem::size_of::<sockaddr_in6>());
17661766
let sin6 = unsafe {
17671767
*(addr as *const _ as *const sockaddr_in6)
17681768
};
@@ -1778,10 +1778,10 @@ pub fn sockaddr_storage_to_addr(
17781778
#[cfg(any(target_os = "android", target_os = "linux"))]
17791779
libc::AF_PACKET => {
17801780
use libc::sockaddr_ll;
1781+
// Don't assert anything about the size.
17811782
// Apparently the Linux kernel can return smaller sizes when
17821783
// the value in the last element of sockaddr_ll (`sll_addr`) is
17831784
// smaller than the declared size of that field
1784-
assert!(len as usize <= mem::size_of::<sockaddr_ll>());
17851785
let sll = unsafe {
17861786
*(addr as *const _ as *const sockaddr_ll)
17871787
};

test/sys/test_socket.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
1+
use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr};
22
use std::collections::hash_map::DefaultHasher;
33
use std::hash::{Hash, Hasher};
4+
use std::mem::{self, MaybeUninit};
45
use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
56
use std::os::unix::io::RawFd;
67
use std::path::Path;
78
use std::slice;
89
use std::str::FromStr;
9-
use libc::c_char;
10+
use libc::{c_char, sockaddr_storage};
1011
#[cfg(any(target_os = "linux", target_os= "android"))]
1112
use crate::*;
1213

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

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

3234
let inet = addr.to_std();
3335
assert_eq!(actual, inet);
36+
37+
let (storage, ffi_size) = {
38+
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
39+
let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>();
40+
let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
41+
assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
42+
unsafe {
43+
storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1);
44+
(storage.assume_init(), ffi_size)
45+
}
46+
};
47+
48+
let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
49+
assert_eq!(from_storage, sockaddr);
50+
let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
51+
assert_eq!(from_storage, sockaddr);
3452
}
3553

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

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

4665
match addr {
4766
InetAddr::V6(addr) => {
@@ -53,6 +72,24 @@ pub fn test_inetv6_addr_to_sock_addr() {
5372
}
5473

5574
assert_eq!(actual, addr.to_std());
75+
76+
let (storage, ffi_size) = {
77+
let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
78+
let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>();
79+
let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
80+
// XXX this does not pass.
81+
// assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
82+
assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize);
83+
unsafe {
84+
storage_ptr.copy_from_nonoverlapping((ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(), 1);
85+
(storage.assume_init(), ffi_size)
86+
}
87+
};
88+
89+
let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
90+
assert_eq!(from_storage, sockaddr);
91+
let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
92+
assert_eq!(from_storage, sockaddr);
5693
}
5794

5895
#[test]
@@ -1169,7 +1206,6 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
11691206
use std::io;
11701207
use std::io::Write;
11711208
use nix::ifaddrs::getifaddrs;
1172-
use nix::sys::socket::SockAddr;
11731209
use nix::net::if_::*;
11741210

11751211
let addrs = match getifaddrs() {

0 commit comments

Comments
 (0)