]> git.proxmox.com Git - rustc.git/blobdiff - vendor/rustix/src/path/arg.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / vendor / rustix / src / path / arg.rs
index 7f66f71f282139a151aecd182b56d99075f3ce41..0ea673d19aef9985401d09fea556320ee59e0ccd 100644 (file)
@@ -15,7 +15,8 @@ use alloc::borrow::Cow;
 use alloc::borrow::ToOwned;
 use alloc::string::String;
 use alloc::vec::Vec;
-use core::str;
+use core::mem::MaybeUninit;
+use core::{ptr, slice, str};
 #[cfg(feature = "std")]
 use std::ffi::{OsStr, OsString};
 #[cfg(feature = "std")]
@@ -931,6 +932,7 @@ impl Arg for DecInt {
 }
 
 /// Runs a closure with `bytes` passed in as a `&CStr`.
+#[allow(unsafe_code, clippy::int_plus_one)]
 #[inline]
 fn with_c_str<T, F>(bytes: &[u8], f: F) -> io::Result<T>
 where
@@ -946,10 +948,26 @@ where
     if bytes.len() >= SMALL_PATH_BUFFER_SIZE {
         return with_c_str_slow_path(bytes, f);
     }
-    let mut buffer: [u8; SMALL_PATH_BUFFER_SIZE] = [0_u8; SMALL_PATH_BUFFER_SIZE];
-    // Copy the bytes in; the buffer already has zeros for the trailing NUL.
-    buffer[..bytes.len()].copy_from_slice(bytes);
-    f(CStr::from_bytes_with_nul(&buffer[..=bytes.len()]).map_err(|_cstr_err| io::Errno::INVAL)?)
+
+    // Taken from
+    // https://github.com/rust-lang/rust/blob/a00f8ba7fcac1b27341679c51bf5a3271fa82df3/library/std/src/sys/common/small_c_string.rs
+    let mut buf = MaybeUninit::<[u8; SMALL_PATH_BUFFER_SIZE]>::uninit();
+    let buf_ptr = buf.as_mut_ptr() as *mut u8;
+
+    // SAFETY: bytes.len() < SMALL_PATH_BUFFER_SIZE which means we have space for
+    // bytes.len() + 1 u8s:
+    debug_assert!(bytes.len() + 1 <= SMALL_PATH_BUFFER_SIZE);
+    unsafe {
+        ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len());
+        buf_ptr.add(bytes.len()).write(0);
+    }
+
+    // SAFETY: we just wrote the bytes above and they will remain valid for the
+    // duration of f b/c buf doesn't get dropped until the end of the function.
+    match CStr::from_bytes_with_nul(unsafe { slice::from_raw_parts(buf_ptr, bytes.len() + 1) }) {
+        Ok(s) => f(s),
+        Err(_) => Err(io::Errno::INVAL),
+    }
 }
 
 /// The slow path which handles any length. In theory OS's only support up