From 0a30fdf85f60a4b95d560e005538215f81f1d9b9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 20 Mar 2020 10:37:29 -0500 Subject: [PATCH] Add a safe method `GuestPtr::copy_from_slice` (#1367) This commit adds a safe method to wiggle pointers to copy slices of data from the host to the guest. --- crates/wiggle/crates/runtime/src/error.rs | 2 ++ crates/wiggle/crates/runtime/src/lib.rs | 29 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/crates/wiggle/crates/runtime/src/error.rs b/crates/wiggle/crates/runtime/src/error.rs index 8a163dbb63..a7bb43fa72 100644 --- a/crates/wiggle/crates/runtime/src/error.rs +++ b/crates/wiggle/crates/runtime/src/error.rs @@ -15,6 +15,8 @@ pub enum GuestError { PtrNotAligned(Region, u32), #[error("Pointer already borrowed: {0:?}")] PtrBorrowed(Region), + #[error("Slice length mismatch")] + SliceLengthsDiffer, #[error("In func {funcname}:{location}:")] InFunc { funcname: &'static str, diff --git a/crates/wiggle/crates/runtime/src/lib.rs b/crates/wiggle/crates/runtime/src/lib.rs index a7f890ca56..11b8ff8608 100644 --- a/crates/wiggle/crates/runtime/src/lib.rs +++ b/crates/wiggle/crates/runtime/src/lib.rs @@ -429,6 +429,35 @@ impl<'a, T> GuestPtr<'a, [T]> { } } + /// Copies the data pointed to by `slice` into this guest region. + /// + /// This method is a *safe* method to copy data from the host to the guest. + /// This requires that `self` and `slice` have the same length. The pointee + /// type `T` requires the [`GuestTypeTransparent`] trait which is an + /// assertion that the representation on the host and on the guest is the + /// same. + /// + /// # Errors + /// + /// Returns an error if this guest pointer is out of bounds or if the length + /// of this guest pointer is not equal to the length of the slice provided. + pub fn copy_from_slice(&self, slice: &[T]) -> Result<(), GuestError> + where + T: GuestTypeTransparent<'a> + Copy, + { + // bounds check ... + let raw = self.as_raw(&mut GuestBorrows::new())?; + unsafe { + // ... length check ... + if (*raw).len() != slice.len() { + return Err(GuestError::SliceLengthsDiffer); + } + // ... and copy! + (*raw).copy_from_slice(slice); + Ok(()) + } + } + /// Returns a `GuestPtr` pointing to the base of the array for the interior /// type `T`. pub fn as_ptr(&self) -> GuestPtr<'a, T> {