wiggle: Refactor with fewer raw pointers (#5268)

This commit refactors the internals of `wiggle` to have fewer raw pointers and more liberally use `&[UnsafeCell<_>]`. The purpose of this refactoring is to more strictly thread through lifetime information throughout the crate to avoid getting it wrong. Additionally storing `UnsafeCell<T>` at rest pushes the unsafety of access to the leaves of modifications where Rust safety guarantees are upheld. Finally this provides what I believe is a safer internal representation of `WasmtimeGuestMemory` since it technically holds onto `&mut [u8]` un-soundly as other `&mut T` pointers are handed out.

Additionally generated `GuestTypeTransparent` impls in the `wiggle` macro were removed because they are not safe for shared memories as-is and otherwise aren't needed for WASI today. The trait has been updated to indicate that all bit patterns must be valid in addition to having the same representation on the host as in the guest to accomodate this.
This commit is contained in:
Alex Crichton
2022-11-15 11:11:47 -06:00
committed by GitHub
parent c2a7ea7e24
commit 6dcdabf37e
8 changed files with 189 additions and 268 deletions

View File

@@ -87,15 +87,5 @@ pub(super) fn define_flags(
#repr::write(&location.cast(), val)
}
}
unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline]
fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> {
use std::convert::TryFrom;
// Validate value in memory using #ident::try_from(reprval)
let reprval = unsafe { (location as *mut #repr).read() };
let _val = #ident::try_from(reprval)?;
Ok(())
}
}
}
}

View File

@@ -70,14 +70,6 @@ pub(super) fn define_handle(
u32::write(&location.cast(), val.0)
}
}
unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline]
fn validate(_location: *mut #ident) -> Result<(), #rt::GuestError> {
// All bit patterns accepted
Ok(())
}
}
}
}

View File

@@ -85,32 +85,6 @@ pub(super) fn define_struct(
(quote!(), quote!(, PartialEq))
};
let transparent = if s.is_transparent() {
let member_validate = s.member_layout().into_iter().map(|ml| {
let offset = ml.offset;
let typename = names.type_ref(&ml.member.tref, anon_lifetime());
quote! {
// SAFETY: caller has validated bounds and alignment of `location`.
// member_layout gives correctly-aligned pointers inside that area.
#typename::validate(
unsafe { (location as *mut u8).add(#offset) as *mut _ }
)?;
}
});
quote! {
unsafe impl<'a> #rt::GuestTypeTransparent<'a> for #ident {
#[inline]
fn validate(location: *mut #ident) -> Result<(), #rt::GuestError> {
#(#member_validate)*
Ok(())
}
}
}
} else {
quote!()
};
quote! {
#[derive(Clone, Debug #extra_derive)]
pub struct #ident #struct_lifetime {
@@ -136,8 +110,6 @@ pub(super) fn define_struct(
Ok(())
}
}
#transparent
}
}

View File

@@ -118,7 +118,7 @@ fn generate_func(
};
let (mem , ctx) = mem.data_and_store_mut(&mut caller);
let ctx = get_cx(ctx);
let mem = #rt::wasmtime::WasmtimeGuestMemory::new(mem, false);
let mem = #rt::wasmtime::WasmtimeGuestMemory::new(mem);
Ok(<#ret_ty>::from(#abi_func(ctx, &mem #(, #arg_names)*) #await_ ?))
};