diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/ffi/c_str.rs | 6 | ||||
| -rw-r--r-- | library/std/src/ffi/c_str/tests.rs | 16 | ||||
| -rw-r--r-- | library/std/src/sys/unix/ext/net/ancillary.rs | 57 |
3 files changed, 54 insertions, 25 deletions
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 687ed61b959..ed4950c57a6 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -613,7 +613,8 @@ impl CString { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { - &self.inner[..self.inner.len() - 1] + // SAFETY: CString has a length at least 1 + unsafe { self.inner.get_unchecked(..self.inner.len() - 1) } } /// Equivalent to [`CString::as_bytes()`] except that the @@ -1322,7 +1323,8 @@ impl CStr { #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); - &bytes[..bytes.len() - 1] + // SAFETY: to_bytes_with_nul returns slice with length at least 1 + unsafe { bytes.get_unchecked(..bytes.len() - 1) } } /// Converts this C string to a byte slice containing the trailing 0 byte. diff --git a/library/std/src/ffi/c_str/tests.rs b/library/std/src/ffi/c_str/tests.rs index 4dff3df63a8..4f7ba9ad437 100644 --- a/library/std/src/ffi/c_str/tests.rs +++ b/library/std/src/ffi/c_str/tests.rs @@ -193,3 +193,19 @@ fn cstr_index_from_empty() { let cstr = CStr::from_bytes_with_nul(original).unwrap(); let _ = &cstr[original.len()..]; } + +#[test] +fn c_string_from_empty_string() { + let original = ""; + let cstring = CString::new(original).unwrap(); + assert_eq!(original.as_bytes(), cstring.as_bytes()); + assert_eq!([b'\0'], cstring.as_bytes_with_nul()); +} + +#[test] +fn c_str_from_empty_string() { + let original = b"\0"; + let cstr = CStr::from_bytes_with_nul(original).unwrap(); + assert_eq!([] as [u8; 0], cstr.to_bytes()); + assert_eq!([b'\0'], cstr.to_bytes_with_nul()); +} diff --git a/library/std/src/sys/unix/ext/net/ancillary.rs b/library/std/src/sys/unix/ext/net/ancillary.rs index 33d6a39af07..011ae643f87 100644 --- a/library/std/src/sys/unix/ext/net/ancillary.rs +++ b/library/std/src/sys/unix/ext/net/ancillary.rs @@ -5,9 +5,7 @@ use crate::marker::PhantomData; use crate::mem::{size_of, zeroed}; use crate::os::unix::io::RawFd; use crate::path::Path; -#[cfg(target_os = "android")] -use crate::ptr::eq; -use crate::ptr::read_unaligned; +use crate::ptr::{eq, read_unaligned}; use crate::slice::from_raw_parts; use crate::sys::net::Socket; @@ -30,12 +28,10 @@ pub(super) fn recv_vectored_with_ancillary_from( ) -> io::Result<(usize, bool, io::Result<SocketAddr>)> { unsafe { let mut msg_name: libc::sockaddr_un = zeroed(); - let mut msg: libc::msghdr = zeroed(); msg.msg_name = &mut msg_name as *mut _ as *mut _; msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t; msg.msg_iov = bufs.as_mut_ptr().cast(); - msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); cfg_if::cfg_if! { if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { msg.msg_iovlen = bufs.len() as libc::size_t; @@ -45,6 +41,7 @@ pub(super) fn recv_vectored_with_ancillary_from( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -52,6 +49,10 @@ pub(super) fn recv_vectored_with_ancillary_from( msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t; } } + // macos requires that the control pointer is NULL when the len is 0. + if msg.msg_controllen > 0 { + msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); + } let count = socket.recv_msg(&mut msg)?; @@ -79,7 +80,6 @@ pub(super) fn send_vectored_with_ancillary_to( msg.msg_name = &mut msg_name as *mut _ as *mut _; msg.msg_namelen = msg_namelen; msg.msg_iov = bufs.as_ptr() as *mut _; - msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); cfg_if::cfg_if! { if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { msg.msg_iovlen = bufs.len() as libc::size_t; @@ -89,6 +89,7 @@ pub(super) fn send_vectored_with_ancillary_to( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -96,6 +97,10 @@ pub(super) fn send_vectored_with_ancillary_to( msg.msg_controllen = ancillary.length as libc::socklen_t; } } + // macos requires that the control pointer is NULL when the len is 0. + if msg.msg_controllen > 0 { + msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); + } ancillary.truncated = false; @@ -147,6 +152,7 @@ fn add_to_ancillary_data<T>( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -159,14 +165,12 @@ fn add_to_ancillary_data<T>( while !cmsg.is_null() { previous_cmsg = cmsg; cmsg = libc::CMSG_NXTHDR(&msg, cmsg); - cfg_if::cfg_if! { - // Android return the same pointer if it is the last cmsg. - // Therefore, check it if the previous pointer is the same as the current one. - if #[cfg(target_os = "android")] { - if cmsg == previous_cmsg { - break; - } - } + + // Most operating systems, but not Linux or emscripten, return the previous pointer + // when its length is zero. Therefore, check if the previous pointer is the same as + // the current one. + if eq(cmsg, previous_cmsg) { + break; } } @@ -184,6 +188,7 @@ fn add_to_ancillary_data<T>( target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -371,6 +376,7 @@ impl<'a> AncillaryData<'a> { target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -421,6 +427,7 @@ impl<'a> Iterator for Messages<'a> { target_os = "emscripten", target_os = "freebsd", all(target_os = "linux", target_env = "musl",), + target_os = "macos", target_os = "netbsd", target_os = "openbsd", ))] { @@ -435,15 +442,13 @@ impl<'a> Iterator for Messages<'a> { }; let cmsg = cmsg.as_ref()?; - cfg_if::cfg_if! { - // Android return the same pointer if it is the last cmsg. - // Therefore, check it if the previous pointer is the same as the current one. - if #[cfg(target_os = "android")] { - if let Some(current) = self.current { - if eq(current, cmsg) { - return None; - } - } + + // Most operating systems, but not Linux or emscripten, return the previous pointer + // when its length is zero. Therefore, check if the previous pointer is the same as + // the current one. + if let Some(current) = self.current { + if eq(current, cmsg) { + return None; } } @@ -514,6 +519,12 @@ impl<'a> SocketAncillary<'a> { self.buffer.len() } + /// Returns `true` if the ancillary data is empty. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn is_empty(&self) -> bool { + self.length == 0 + } + /// Returns the number of used bytes. #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn len(&self) -> usize { |
