-
Notifications
You must be signed in to change notification settings - Fork 66
Closed
Description
The problem code is here:
Lines 87 to 142 in 77a6eb4
| fn addr2raw(addr: &SocketAddr) -> (*const c::sockaddr, c::socklen_t) { | |
| match *addr { | |
| SocketAddr::V4(ref a) => { | |
| (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) | |
| } | |
| SocketAddr::V6(ref a) => { | |
| (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t) | |
| } | |
| } | |
| } | |
| fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr> { | |
| match storage.ss_family as c_int { | |
| c::AF_INET => { | |
| unsafe { | |
| assert!(len as usize >= mem::size_of::<c::sockaddr_in>()); | |
| let sa = storage as *const _ as *const c::sockaddr_in; | |
| let bits = c::sockaddr_in_u32(&(*sa)); | |
| let ip = Ipv4Addr::new((bits >> 24) as u8, | |
| (bits >> 16) as u8, | |
| (bits >> 8) as u8, | |
| bits as u8); | |
| Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port)))) | |
| } | |
| } | |
| c::AF_INET6 => { | |
| unsafe { | |
| assert!(len as usize >= mem::size_of::<c::sockaddr_in6>()); | |
| let sa = storage as *const _ as *const c::sockaddr_in6; | |
| #[cfg(windows)] let arr = (*sa).sin6_addr.u.Byte(); | |
| #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr; | |
| let ip = Ipv6Addr::new( | |
| (arr[0] as u16) << 8 | (arr[1] as u16), | |
| (arr[2] as u16) << 8 | (arr[3] as u16), | |
| (arr[4] as u16) << 8 | (arr[5] as u16), | |
| (arr[6] as u16) << 8 | (arr[7] as u16), | |
| (arr[8] as u16) << 8 | (arr[9] as u16), | |
| (arr[10] as u16) << 8 | (arr[11] as u16), | |
| (arr[12] as u16) << 8 | (arr[13] as u16), | |
| (arr[14] as u16) << 8 | (arr[15] as u16), | |
| ); | |
| #[cfg(windows)] let sin6_scope_id = *(*sa).u.sin6_scope_id(); | |
| #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id; | |
| Ok(SocketAddr::V6(SocketAddrV6::new(ip, | |
| ::ntoh((*sa).sin6_port), | |
| (*sa).sin6_flowinfo, | |
| sin6_scope_id))) | |
| } | |
| } | |
| _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")), | |
| } | |
| } |
It assumes that the layout of std::net::SocketAddrV{4,6} matches libc::sockaddr, but this can't be assumed.
Related issues: tokio-rs/mio#1386, rust-lang/socket2#119, rust-lang/rust#78802.
Mio has roughly the same code, this was fixed in tokio-rs/mio#1388, for socket2: rust-lang/socket2#120.
Metadata
Metadata
Assignees
Labels
No labels