Skip to content

Commit

Permalink
Merge pull request #18
Browse files Browse the repository at this point in the history
Fix from_raw() and new_unspecified()
  • Loading branch information
tormol authored Oct 17, 2023
2 parents 3f6ad99 + da6d387 commit a367f45
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 5 deletions.
11 changes: 6 additions & 5 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl UnixSocketAddr {
let mut addr: sockaddr_un = unsafe { mem::zeroed() };
addr.sun_family = AF_UNIX as sa_family_t;
UnixSocketAddr {
len: mem::size_of::<sa_family_t>() as socklen_t,
len: path_offset(),
addr,
}
}
Expand Down Expand Up @@ -672,16 +672,17 @@ impl UnixSocketAddr {
} else if addr.is_null() {
Err(io::Error::new(ErrorKind::InvalidInput, "addr is NULL"))
} else if len < path_offset() {
Err(io::Error::new(ErrorKind::InvalidInput, "address length is too low"))
} else if len > path_offset() + mem::size_of_val(&copy.addr.sun_path) as socklen_t {
Err(io::Error::new(ErrorKind::InvalidInput, "address length is too short"))
} else if len > mem::size_of::<sockaddr_un>() as socklen_t {
Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC))
} else if (&*addr).sa_family != AF_UNIX as sa_family_t {
Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"))
} else {
let addr = addr as *const sockaddr_un;
let sun_path_ptr = (&*addr).sun_path.as_ptr();
let sun_path = slice::from_raw_parts(sun_path_ptr, len as usize);
copy.addr.sun_path.copy_from_slice(sun_path);
let path_len = (len - path_offset()) as usize;
let sun_path = slice::from_raw_parts(sun_path_ptr, path_len);
copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
copy.len = len;
Ok(copy)
}
Expand Down
84 changes: 84 additions & 0 deletions tests/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,87 @@ fn datagram_peek_vectored() {
std::fs::remove_file("datagram_server.sock").unwrap();
let _ = std::fs::remove_file("datagram_client.sock");
}

#[test]
fn from_raw_path() {
let path_addr = UnixSocketAddr::from_path("a/path.sock").unwrap();
let a = unsafe {
let (raw_addr, raw_len) = path_addr.as_raw();
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len)
}.expect("from_raw() accepts from_path()");
assert_eq!(a, path_addr);
assert!(a.is_path());
}

#[test]
fn from_raw_max_len_path() {
let path = "R".repeat(UnixSocketAddr::max_path_len());
let path_addr = UnixSocketAddr::from_path(path.as_str()).unwrap();
let a = unsafe {
let (raw_addr, raw_len) = path_addr.as_raw();
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len)
}.expect("from_path() is valid");
assert_eq!(a, path_addr);
assert!(a.is_path());
}

#[test]
fn from_raw_too_long_path() {
#[repr(C)]
struct TooLong {
fam: libc::sa_family_t,
path: [u8; 300],
}
let path_addr = TooLong {
fam: libc::AF_UNIX as libc::sa_family_t,
path: [b'o'; 300],
};
unsafe {
let raw_addr = &path_addr as *const TooLong as *const sockaddr;
UnixSocketAddr::from_raw(raw_addr, size_of::<TooLong>() as _)
}.expect_err("too long");
}

#[test]
fn from_raw_empty() {
let unspecified_addr = UnixSocketAddr::new_unspecified();
let (raw_addr, raw_len) = unspecified_addr.as_raw();
let a = unsafe {
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len)
}.expect("from_raw() accepts new_unspecified()");
assert_eq!(a, unspecified_addr);
assert!(a.is_unnamed());

if !UnixSocketAddr::has_abstract_addresses() {
let a = unsafe {
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len+10)
}.expect("from_raw() accepts extra NULs");
assert_eq!(a, unspecified_addr);
assert!(a.is_unnamed());
}
}

#[cfg(any(target_os="linux", target_os="android"))]
#[test]
fn from_raw_abstract() {
let abstract_addr = UnixSocketAddr::from_abstract(b"aa!").unwrap();
let a = unsafe {
let (raw_addr, raw_len) = abstract_addr.as_raw();
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len)
}.expect("from_raw() accepts from_abstract()");
assert_eq!(a, abstract_addr);
assert!(a.is_abstract());

let max_abstract = "l".repeat(UnixSocketAddr::max_abstract_len());
let abstract_addr = UnixSocketAddr::from_abstract(max_abstract.as_bytes()).unwrap();
let (raw_addr, raw_len) = abstract_addr.as_raw();
let a = unsafe {
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len)
}.expect("from_raw() accepts longest abstract");
assert_eq!(a, abstract_addr);
assert!(a.is_abstract());

unsafe {
UnixSocketAddr::from_raw(raw_addr as *const sockaddr_un as *const sockaddr, raw_len+1)
}.expect_err("from_raw() rejects too long abstract");
}

0 comments on commit a367f45

Please sign in to comment.