Segfault-based memory bounds-checking. (#29)

* Mostly working

* Improve CircleCI releases

* Recover safely from WebAssembly-generated traps

* Add notes about async signal safety

* Improved trap catching with call_protected macro

* Improved test assert_trap code using call_protected macro

* Mostly working
This commit is contained in:
Lachlan Sneff
2018-11-25 13:51:21 -05:00
parent 5feda6b524
commit 75ef87824e
9 changed files with 93 additions and 107 deletions

View File

@ -31,6 +31,7 @@ use super::module::{Export, ImportableExportable, Module};
use super::relocation::{Reloc, RelocSink, RelocationType};
type TablesSlice = UncheckedSlice<BoundedSlice<usize>>;
// TODO: this should be `type MemoriesSlice = UncheckedSlice<UncheckedSlice<u8>>;`, but that crashes for some reason.
type MemoriesSlice = UncheckedSlice<BoundedSlice<u8>>;
type GlobalsSlice = UncheckedSlice<u8>;
@ -452,8 +453,14 @@ impl Instance {
for init in &module.info.data_initializers {
debug_assert!(init.base.is_none(), "globalvar base not supported yet");
let offset = init.offset;
let mem_mut = memories[init.memory_index.index()].as_mut();
let to_init = &mut mem_mut[offset..offset + init.data.len()];
let mem = &mut memories[init.memory_index.index()];
let end_of_init = offset + init.data.len();
if end_of_init > mem.current_size() {
let grow_pages = (end_of_init / LinearMemory::WASM_PAGE_SIZE) + 1;
mem.grow(grow_pages as u32)
.expect("failed to grow memory for data initializers");
}
let to_init = &mut mem[offset..offset + init.data.len()];
to_init.copy_from_slice(&init.data);
}
crate::apis::emscripten::emscripten_set_up_memory(&mut memories[0]);
@ -475,7 +482,7 @@ impl Instance {
.map(|mem| {
BoundedSlice::new(
&mem[..],
mem.current as usize * LinearMemory::WASM_PAGE_SIZE,
mem.current_size(),
)
})
.collect();
@ -535,8 +542,10 @@ impl Instance {
.as_ref()[address..address + len]
}
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const u8 {
&self.data_pointers.memories.get_unchecked(index)[offset] as *const u8
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize {
let memories: &[LinearMemory] = &self.memories[..];
let mem = &memories[index];
unsafe { mem[..].as_ptr().add(offset) as *const usize }
}
// Shows the value of a global variable.
@ -564,21 +573,10 @@ extern "C" fn grow_memory(size: u32, memory_index: u32, instance: &mut Instance)
.grow(size)
.unwrap_or(-1);
if old_mem_size != -1 {
// Get new memory bytes
let new_mem_bytes = (old_mem_size as usize + size as usize) * LinearMemory::WASM_PAGE_SIZE;
// Update data_pointer
instance
.data_pointers
.memories
.get_unchecked_mut(memory_index as usize)
.len = new_mem_bytes;
}
old_mem_size
}
extern "C" fn current_memory(memory_index: u32, instance: &mut Instance) -> u32 {
let memory = &instance.memories[memory_index as usize];
memory.current_size() as u32
memory.current_pages() as u32
}