Browse Source
* wiggle-runtime: add as_raw method for [T] * add trivial borrow checker back in * integrate runtime borrow checker with as_raw methods * handle pointer arith overflow correctly in as_raw, create PtrOverflow error * runtime: add validation back to GuestType * generate: impl validate for enums, flags, handles, ints * oops! make validate its own method on trait GuestTypeTransparent * fix transparent impls for enum, flag, handle, int * some structs are transparent. fix tests. * tests: define byte_slice_strat and friends * wiggle-tests: i believe my allocator is working now * some type juggling around memset for ease of use * make GuestTypeTransparent an unsafe trait * delete redundant validation of pointer align * fix doc * wiggle_test: aha, you cant use sets to track memory areas * add multi-string test which exercises the runtime borrow checker against HostMemory::byte_slice_strat * oops left debug panic in * remove redundant (& incorrect, since unchecked) length calc * redesign validate again, and actually hook to as_raw * makr all validate impls as inline this should hopefully allow as_raw's check loop to be unrolled to a no-op in most cases! * code review fixespull/1278/head
Pat Hickey
5 years ago
committed by
GitHub
18 changed files with 655 additions and 50 deletions
@ -0,0 +1,91 @@ |
|||
use crate::region::Region; |
|||
use crate::GuestError; |
|||
|
|||
#[derive(Debug)] |
|||
pub struct GuestBorrows { |
|||
borrows: Vec<Region>, |
|||
} |
|||
|
|||
impl GuestBorrows { |
|||
pub fn new() -> Self { |
|||
Self { |
|||
borrows: Vec::new(), |
|||
} |
|||
} |
|||
|
|||
fn is_borrowed(&self, r: Region) -> bool { |
|||
!self.borrows.iter().all(|b| !b.overlaps(r)) |
|||
} |
|||
|
|||
pub fn borrow(&mut self, r: Region) -> Result<(), GuestError> { |
|||
if self.is_borrowed(r) { |
|||
Err(GuestError::PtrBorrowed(r)) |
|||
} else { |
|||
self.borrows.push(r); |
|||
Ok(()) |
|||
} |
|||
} |
|||
} |
|||
|
|||
#[cfg(test)] |
|||
mod test { |
|||
use super::*; |
|||
#[test] |
|||
fn nonoverlapping() { |
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(0, 10); |
|||
let r2 = Region::new(10, 10); |
|||
assert!(!r1.overlaps(r2)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
bs.borrow(r2).expect("can borrow r2"); |
|||
|
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(10, 10); |
|||
let r2 = Region::new(0, 10); |
|||
assert!(!r1.overlaps(r2)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
bs.borrow(r2).expect("can borrow r2"); |
|||
} |
|||
|
|||
#[test] |
|||
fn overlapping() { |
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(0, 10); |
|||
let r2 = Region::new(9, 10); |
|||
assert!(r1.overlaps(r2)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
assert!(bs.borrow(r2).is_err(), "cant borrow r2"); |
|||
|
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(0, 10); |
|||
let r2 = Region::new(2, 5); |
|||
assert!(r1.overlaps(r2)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
assert!(bs.borrow(r2).is_err(), "cant borrow r2"); |
|||
|
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(9, 10); |
|||
let r2 = Region::new(0, 10); |
|||
assert!(r1.overlaps(r2)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
assert!(bs.borrow(r2).is_err(), "cant borrow r2"); |
|||
|
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(2, 5); |
|||
let r2 = Region::new(0, 10); |
|||
assert!(r1.overlaps(r2)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
assert!(bs.borrow(r2).is_err(), "cant borrow r2"); |
|||
|
|||
let mut bs = GuestBorrows::new(); |
|||
let r1 = Region::new(2, 5); |
|||
let r2 = Region::new(10, 5); |
|||
let r3 = Region::new(15, 5); |
|||
let r4 = Region::new(0, 10); |
|||
assert!(r1.overlaps(r4)); |
|||
bs.borrow(r1).expect("can borrow r1"); |
|||
bs.borrow(r2).expect("can borrow r2"); |
|||
bs.borrow(r3).expect("can borrow r3"); |
|||
assert!(bs.borrow(r4).is_err(), "cant borrow r4"); |
|||
} |
|||
} |
Loading…
Reference in new issue