Removed Instance::new_no_memory_init, use custom LinearMemory with custom memory_init method to get the same result

This commit is contained in:
ptitSeb
2022-10-04 14:48:51 +02:00
parent d581152641
commit c27547e41e
6 changed files with 53 additions and 76 deletions

View File

@@ -118,47 +118,7 @@ impl Instance {
let imports = imports let imports = imports
.imports_for_module(module) .imports_for_module(module)
.map_err(InstantiationError::Link)?; .map_err(InstantiationError::Link)?;
let mut handle = module.instantiate(store, &imports, true)?; let mut handle = module.instantiate(store, &imports)?;
let exports = module
.exports()
.map(|export| {
let name = export.name().to_string();
let export = handle.lookup(&name).expect("export");
let extern_ = Extern::from_vm_extern(store, export);
(name, extern_)
})
.collect::<Exports>();
let instance = Self {
_handle: StoreHandle::new(store.objects_mut(), handle),
module: module.clone(),
exports,
};
Ok(instance)
}
#[cfg(feature = "compiler")]
/// Creates a new `Instance` from a WebAssembly [`Module`] and a
/// set of imports using [`Imports`] or the [`imports`] macro helper.
/// The instance memory will not be initialized
///
/// ## Errors
///
/// The function can return [`InstantiationError`]s.
///
/// Those are, as defined by the spec:
/// * Link errors that happen when plugging the imports into the instance
/// * Runtime errors that happen when running the module `start` function.
pub fn new_no_memory_init(
store: &mut impl AsStoreMut,
module: &Module,
imports: &Imports,
) -> Result<Self, InstantiationError> {
let imports = imports
.imports_for_module(module)
.map_err(InstantiationError::Link)?;
let mut handle = module.instantiate(store, &imports, false)?;
let exports = module let exports = module
.exports() .exports()
.map(|export| { .map(|export| {
@@ -195,7 +155,7 @@ impl Instance {
externs: &[Extern], externs: &[Extern],
) -> Result<Self, InstantiationError> { ) -> Result<Self, InstantiationError> {
let imports = externs.to_vec(); let imports = externs.to_vec();
let mut handle = module.instantiate(store, &imports, true)?; let mut handle = module.instantiate(store, &imports)?;
let exports = module let exports = module
.exports() .exports()
.map(|export| { .map(|export| {

View File

@@ -343,7 +343,6 @@ impl Module {
&self, &self,
store: &mut impl AsStoreMut, store: &mut impl AsStoreMut,
imports: &[crate::Extern], imports: &[crate::Extern],
initialize_memory: bool,
) -> Result<InstanceHandle, InstantiationError> { ) -> Result<InstanceHandle, InstantiationError> {
// Ensure all imports come from the same context. // Ensure all imports come from the same context.
for import in imports { for import in imports {
@@ -371,7 +370,6 @@ impl Module {
self.artifact.finish_instantiation( self.artifact.finish_instantiation(
store.as_store_ref().signal_handler(), store.as_store_ref().signal_handler(),
&mut instance_handle, &mut instance_handle,
initialize_memory,
)?; )?;
Ok(instance_handle) Ok(instance_handle)

View File

@@ -245,6 +245,13 @@ mod tests {
fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>> { fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>> {
None None
} }
/*
// this code allow custom memory to be ignoring init_memory
use wasmer_vm::Trap;
unsafe fn initialize_with_data(&self, _start: usize, _data: &[u8]) -> Result<(), Trap> {
Ok(())
}
*/
} }
impl From<VMTinyMemory> for wasmer_vm::VMMemory { impl From<VMTinyMemory> for wasmer_vm::VMMemory {

View File

@@ -398,7 +398,6 @@ impl Artifact {
&self, &self,
trap_handler: Option<*const TrapHandlerFn<'static>>, trap_handler: Option<*const TrapHandlerFn<'static>>,
handle: &mut InstanceHandle, handle: &mut InstanceHandle,
initialize_memory: bool,
) -> Result<(), InstantiationError> { ) -> Result<(), InstantiationError> {
let data_initializers = self let data_initializers = self
.data_initializers() .data_initializers()
@@ -409,7 +408,7 @@ impl Artifact {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
handle handle
.finish_instantiation(trap_handler, &data_initializers, initialize_memory) .finish_instantiation(trap_handler, &data_initializers)
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap))) .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
} }

View File

@@ -206,6 +206,7 @@ impl Instance {
unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tables_begin()) } unsafe { self.vmctx_plus_offset(self.offsets.vmctx_tables_begin()) }
} }
#[allow(dead_code)]
/// Get a locally defined or imported memory. /// Get a locally defined or imported memory.
fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition { fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition {
if let Some(local_index) = self.module.local_memory_index(index) { if let Some(local_index) = self.module.local_memory_index(index) {
@@ -240,6 +241,21 @@ impl Instance {
unsafe { self.vmctx_plus_offset(self.offsets.vmctx_memories_begin()) } unsafe { self.vmctx_plus_offset(self.offsets.vmctx_memories_begin()) }
} }
/// Get a locally defined or imported memory.
fn get_vmmemory(&self, index: MemoryIndex) -> &VMMemory {
if let Some(local_index) = self.module.local_memory_index(index) {
unsafe {
self.memories
.get(local_index)
.unwrap()
.get(self.context.as_ref().unwrap())
}
} else {
let import = self.imported_memory(index);
unsafe { import.handle.get(self.context.as_ref().unwrap()) }
}
}
/// Return the indexed `VMGlobalDefinition`. /// Return the indexed `VMGlobalDefinition`.
fn global(&self, index: LocalGlobalIndex) -> VMGlobalDefinition { fn global(&self, index: LocalGlobalIndex) -> VMGlobalDefinition {
unsafe { self.global_ptr(index).as_ref().clone() } unsafe { self.global_ptr(index).as_ref().clone() }
@@ -701,29 +717,18 @@ impl Instance {
) -> Result<(), Trap> { ) -> Result<(), Trap> {
// https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-memory-init // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-memory-init
let memory = self.get_memory(memory_index); let memory = self.get_vmmemory(memory_index);
let passive_data = self.passive_data.borrow(); let passive_data = self.passive_data.borrow();
let data = passive_data.get(&data_index).map_or(&[][..], |d| &**d); let data = passive_data.get(&data_index).map_or(&[][..], |d| &**d);
if src if src
.checked_add(len) .checked_add(len)
.map_or(true, |n| n as usize > data.len()) .map_or(true, |end| end as usize > data.len())
|| dst.checked_add(len).map_or(true, |m| {
usize::try_from(m).unwrap() > memory.current_length
})
{ {
return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds)); return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
} }
let src_slice = &data[src as usize..(src + len) as usize]; let src_slice = &data[src as usize..(src + len) as usize];
unsafe { memory.initialize_with_data(dst as usize, src_slice) }
unsafe {
let dst_start = memory.base.add(dst as usize);
let dst_slice = slice::from_raw_parts_mut(dst_start, len as usize);
dst_slice.copy_from_slice(src_slice);
}
Ok(())
} }
/// Drop the given data segment, truncating its length to zero. /// Drop the given data segment, truncating its length to zero.
@@ -947,15 +952,12 @@ impl InstanceHandle {
&mut self, &mut self,
trap_handler: Option<*const TrapHandlerFn<'static>>, trap_handler: Option<*const TrapHandlerFn<'static>>,
data_initializers: &[DataInitializer<'_>], data_initializers: &[DataInitializer<'_>],
initialize_memory: bool,
) -> Result<(), Trap> { ) -> Result<(), Trap> {
let instance = self.instance_mut(); let instance = self.instance_mut();
// Apply the initializers. // Apply the initializers.
initialize_tables(instance)?; initialize_tables(instance)?;
if initialize_memory { initialize_memories(instance, data_initializers)?;
initialize_memories(instance, data_initializers)?;
}
// The WebAssembly spec specifies that the start function is // The WebAssembly spec specifies that the start function is
// invoked automatically at instantiation time. // invoked automatically at instantiation time.
@@ -1150,6 +1152,7 @@ fn get_memory_init_start(init: &DataInitializer<'_>, instance: &Instance) -> usi
} }
#[allow(clippy::mut_from_ref)] #[allow(clippy::mut_from_ref)]
#[allow(dead_code)]
/// Return a byte-slice view of a memory's data. /// Return a byte-slice view of a memory's data.
unsafe fn get_memory_slice<'instance>( unsafe fn get_memory_slice<'instance>(
init: &DataInitializer<'_>, init: &DataInitializer<'_>,
@@ -1245,21 +1248,11 @@ fn initialize_memories(
data_initializers: &[DataInitializer<'_>], data_initializers: &[DataInitializer<'_>],
) -> Result<(), Trap> { ) -> Result<(), Trap> {
for init in data_initializers { for init in data_initializers {
let memory = instance.get_memory(init.location.memory_index); let memory = instance.get_vmmemory(init.location.memory_index);
let start = get_memory_init_start(init, instance); let start = get_memory_init_start(init, instance);
if start
.checked_add(init.data.len())
.map_or(true, |end| end > memory.current_length)
{
return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
}
unsafe { unsafe {
let mem_slice = get_memory_slice(init, instance); memory.initialize_with_data(start, init.data)?;
let end = start + init.data.len();
let to_init = &mut mem_slice[start..end];
to_init.copy_from_slice(init.data);
} }
} }

View File

@@ -5,11 +5,13 @@
//! //!
//! `Memory` is to WebAssembly linear memories what `Table` is to WebAssembly tables. //! `Memory` is to WebAssembly linear memories what `Table` is to WebAssembly tables.
use crate::trap::{Trap, TrapCode};
use crate::{mmap::Mmap, store::MaybeInstanceOwned, vmcontext::VMMemoryDefinition}; use crate::{mmap::Mmap, store::MaybeInstanceOwned, vmcontext::VMMemoryDefinition};
use more_asserts::assert_ge; use more_asserts::assert_ge;
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::convert::TryInto; use std::convert::TryInto;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice;
use wasmer_types::{Bytes, MemoryError, MemoryStyle, MemoryType, Pages}; use wasmer_types::{Bytes, MemoryError, MemoryStyle, MemoryType, Pages};
// The memory mapped area // The memory mapped area
@@ -410,4 +412,22 @@ where
/// Attempts to clone this memory (if its clonable) /// Attempts to clone this memory (if its clonable)
fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>>; fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>>;
#[doc(hidden)]
unsafe fn initialize_with_data(&self, start: usize, data: &[u8]) -> Result<(), Trap> {
let memory = self.vmmemory().as_ref();
if start
.checked_add(data.len())
.map_or(true, |end| end > memory.current_length)
{
return Err(Trap::lib(TrapCode::HeapAccessOutOfBounds));
}
let mem_slice = slice::from_raw_parts_mut(memory.base, memory.current_length);
let end = start + data.len();
let to_init = &mut mem_slice[start..end];
to_init.copy_from_slice(data);
Ok(())
}
} }