Skip to content

Commit

Permalink
Fix c_char vs u8 errors in the linux_raw backend. (#971)
Browse files Browse the repository at this point in the history
* Fix `c_char` vs `u8` errors in the linux_raw backend.

Fix the linux_raw backend to handle the case where linux-raw-sys defines
`c_char` as `i8`.

linux-raw-sys used to always define `c_char` as `u8` because it usually
isn't important to match the platform `char` type, but that makes it
inconvenient to work with Rust's `CStr`/`CString` types which use `c_char`,
so linux-raw-sys has started defining `c_char` as `i8` on platforms
which define it that way.

* Fix redundant `unsafe` blocks.
  • Loading branch information
sunfishcode authored Dec 9, 2023
1 parent b1f8c8f commit 3758947
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 20 deletions.
22 changes: 18 additions & 4 deletions src/backend/linux_raw/net/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{io, path};
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::slice;

/// `struct sockaddr_un`
#[derive(Clone)]
Expand All @@ -36,7 +37,7 @@ impl SocketAddrUnix {
return Err(io::Errno::NAMETOOLONG);
}
for (i, b) in bytes.iter().enumerate() {
unix.sun_path[i] = *b;
unix.sun_path[i] = *b as _;
}
let len = offsetof_sun_path() + bytes.len();
let len = len.try_into().unwrap();
Expand All @@ -48,6 +49,10 @@ impl SocketAddrUnix {
pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
let mut unix = Self::init();
let id = &mut unix.sun_path[1..];

// SAFETY: Convert `&mut [c_char]` to `&mut [u8]`.
let id = unsafe { slice::from_raw_parts_mut(id.as_mut_ptr().cast::<u8>(), id.len()) };

if let Some(id) = id.get_mut(..name.len()) {
id.copy_from_slice(name);
let len = offsetof_sun_path() + 1 + name.len();
Expand All @@ -69,9 +74,13 @@ impl SocketAddrUnix {
#[inline]
pub fn path(&self) -> Option<&CStr> {
let len = self.len();
if len != 0 && self.unix.sun_path[0] != b'\0' {
if len != 0 && self.unix.sun_path[0] as u8 != b'\0' {
let end = len as usize - offsetof_sun_path();
let bytes = &self.unix.sun_path[..end];

// SAFETY: Convert `&[c_char]` to `&[u8]`.
let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len()) };

// SAFETY: `from_bytes_with_nul_unchecked` since the string is
// NUL-terminated.
unsafe { Some(CStr::from_bytes_with_nul_unchecked(bytes)) }
Expand All @@ -84,9 +93,14 @@ impl SocketAddrUnix {
#[inline]
pub fn abstract_name(&self) -> Option<&[u8]> {
let len = self.len();
if len != 0 && self.unix.sun_path[0] == b'\0' {
if len != 0 && self.unix.sun_path[0] as u8 == b'\0' {
let end = len as usize - offsetof_sun_path();
Some(&self.unix.sun_path[1..end])
let bytes = &self.unix.sun_path[1..end];

// SAFETY: Convert `&[c_char]` to `&[u8]`.
let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len()) };

Some(bytes)
} else {
None
}
Expand Down
42 changes: 26 additions & 16 deletions src/backend/linux_raw/net/read_sockaddr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::backend::c;
use crate::io;
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
use core::mem::size_of;
use core::slice;

// This must match the header of `sockaddr`.
#[repr(C)]
Expand Down Expand Up @@ -93,17 +94,22 @@ pub(crate) unsafe fn read_sockaddr(
//
// [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html
if decode.sun_path[0] == 0 {
return SocketAddrUnix::new_abstract_name(
&decode.sun_path[1..len - offsetof_sun_path],
)
.map(SocketAddrAny::Unix);
let bytes = &decode.sun_path[1..len - offsetof_sun_path];

// SAFETY: Convert `&[c_char]` to `&[u8]`.
let bytes = slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len());

return SocketAddrUnix::new_abstract_name(bytes).map(SocketAddrAny::Unix);
}

// Otherwise we expect a NUL-terminated filesystem path.
let bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];

// SAFETY: Convert `&[c_char]` to `&[u8]`.
let bytes = slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len());

assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0);
Ok(SocketAddrAny::Unix(SocketAddrUnix::new(
&decode.sun_path[..len - 1 - offsetof_sun_path],
)?))
Ok(SocketAddrAny::Unix(SocketAddrUnix::new(bytes)?))
}
}
_ => Err(io::Errno::NOTSUP),
Expand Down Expand Up @@ -165,19 +171,23 @@ pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) -
//
// [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html
if decode.sun_path[0] == 0 {
return SocketAddrAny::Unix(
SocketAddrUnix::new_abstract_name(
&decode.sun_path[1..len - offsetof_sun_path],
)
.unwrap(),
);
let bytes = &decode.sun_path[1..len - offsetof_sun_path];

// SAFETY: Convert `&[c_char]` to `&[u8]`.
let bytes = slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len());

return SocketAddrAny::Unix(SocketAddrUnix::new_abstract_name(bytes).unwrap());
}

// Otherwise we expect a NUL-terminated filesystem path.
assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0);
SocketAddrAny::Unix(
SocketAddrUnix::new(&decode.sun_path[..len - 1 - offsetof_sun_path]).unwrap(),
)

let bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];

// SAFETY: Convert `&[c_char]` to `&[u8]`.
let bytes = slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len());

SocketAddrAny::Unix(SocketAddrUnix::new(bytes).unwrap())
}
}
other => unimplemented!("{:?}", other),
Expand Down

0 comments on commit 3758947

Please sign in to comment.