From 2139020d6dd1230868318013a352bc848c702f50 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Tue, 10 Mar 2020 12:33:02 -0700 Subject: [PATCH] add manual interface for borrowing a GuestPtr (#40) * add manual interface for borrowing a GuestPtr * add manual borrow checking methods for slice and str as well * update test to use borrow_slice --- crates/runtime/src/borrow.rs | 39 ++++++++++++++++++++++++++++++++++-- tests/wasi.rs | 10 +++++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/runtime/src/borrow.rs b/crates/runtime/src/borrow.rs index 5c3c80f429..8d5d81c01a 100644 --- a/crates/runtime/src/borrow.rs +++ b/crates/runtime/src/borrow.rs @@ -1,5 +1,5 @@ use crate::region::Region; -use crate::GuestError; +use crate::{GuestError, GuestPtr, GuestType}; #[derive(Debug)] pub struct GuestBorrows { @@ -17,7 +17,7 @@ impl GuestBorrows { !self.borrows.iter().all(|b| !b.overlaps(r)) } - pub fn borrow(&mut self, r: Region) -> Result<(), GuestError> { + pub(crate) fn borrow(&mut self, r: Region) -> Result<(), GuestError> { if self.is_borrowed(r) { Err(GuestError::PtrBorrowed(r)) } else { @@ -25,6 +25,41 @@ impl GuestBorrows { Ok(()) } } + + /// Borrow the region of memory pointed to by a `GuestPtr`. This is required for safety if + /// you are dereferencing `GuestPtr`s while holding a reference to a slice via + /// `GuestPtr::as_raw`. + pub fn borrow_pointee<'a, T>(&mut self, p: &GuestPtr<'a, T>) -> Result<(), GuestError> + where + T: GuestType<'a>, + { + self.borrow(Region { + start: p.offset(), + len: T::guest_size(), + }) + } + + /// Borrow the slice of memory pointed to by a `GuestPtr<[T]>`. This is required for safety if + /// you are dereferencing the `GuestPtr`s while holding a reference to another slice via + /// `GuestPtr::as_raw`. Not required if using `GuestPtr::as_raw` on this pointer. + pub fn borrow_slice<'a, T>(&mut self, p: &GuestPtr<'a, [T]>) -> Result<(), GuestError> + where + T: GuestType<'a>, + { + let (start, elems) = p.offset(); + let len = T::guest_size() + .checked_mul(elems) + .ok_or_else(|| GuestError::PtrOverflow)?; + self.borrow(Region { start, len }) + } + + /// Borrow the slice of memory pointed to by a `GuestPtr`. This is required for safety if + /// you are dereferencing the `GuestPtr`s while holding a reference to another slice via + /// `GuestPtr::as_raw`. Not required if using `GuestPtr::as_raw` on this pointer. + pub fn borrow_str(&mut self, p: &GuestPtr) -> Result<(), GuestError> { + let (start, len) = p.offset(); + self.borrow(Region { start, len }) + } } #[cfg(test)] diff --git a/tests/wasi.rs b/tests/wasi.rs index 0b27fb3ea0..accefb7584 100644 --- a/tests/wasi.rs +++ b/tests/wasi.rs @@ -129,11 +129,13 @@ impl crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let mut bc = GuestBorrows::new(); let mut slices: Vec<&'_ mut [u8]> = Vec::new(); + // Mark the iov elements as borrowed, to ensure that they does not + // overlap with any of the as_raw regions. + bc.borrow_slice(&iovs).expect("borrow iovec array"); for iov_ptr in iovs.iter() { - let iov: types::Iovec = iov_ptr - .expect("iovec element pointer is valid") - .read() - .expect("read iovec element"); + let iov_ptr = iov_ptr.expect("iovec element pointer is valid"); + + let iov: types::Iovec = iov_ptr.read().expect("read iovec element"); let base: GuestPtr = iov.buf; let len: u32 = iov.buf_len; let buf: GuestPtr<[u8]> = base.as_array(len);