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
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
use crate::region::Region;
|
use crate::region::Region;
|
||||||
use crate::GuestError;
|
use crate::{GuestError, GuestPtr, GuestType};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GuestBorrows {
|
pub struct GuestBorrows {
|
||||||
@@ -17,7 +17,7 @@ impl GuestBorrows {
|
|||||||
!self.borrows.iter().all(|b| !b.overlaps(r))
|
!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) {
|
if self.is_borrowed(r) {
|
||||||
Err(GuestError::PtrBorrowed(r))
|
Err(GuestError::PtrBorrowed(r))
|
||||||
} else {
|
} else {
|
||||||
@@ -25,6 +25,41 @@ impl GuestBorrows {
|
|||||||
Ok(())
|
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<str>`. 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<str>) -> Result<(), GuestError> {
|
||||||
|
let (start, len) = p.offset();
|
||||||
|
self.borrow(Region { start, len })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -129,11 +129,13 @@ impl crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
|
|
||||||
let mut bc = GuestBorrows::new();
|
let mut bc = GuestBorrows::new();
|
||||||
let mut slices: Vec<&'_ mut [u8]> = Vec::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() {
|
for iov_ptr in iovs.iter() {
|
||||||
let iov: types::Iovec = iov_ptr
|
let iov_ptr = iov_ptr.expect("iovec element pointer is valid");
|
||||||
.expect("iovec element pointer is valid")
|
|
||||||
.read()
|
let iov: types::Iovec = iov_ptr.read().expect("read iovec element");
|
||||||
.expect("read iovec element");
|
|
||||||
let base: GuestPtr<u8> = iov.buf;
|
let base: GuestPtr<u8> = iov.buf;
|
||||||
let len: u32 = iov.buf_len;
|
let len: u32 = iov.buf_len;
|
||||||
let buf: GuestPtr<[u8]> = base.as_array(len);
|
let buf: GuestPtr<[u8]> = base.as_array(len);
|
||||||
|
|||||||
Reference in New Issue
Block a user