mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-13 05:48:45 +00:00
Make all tests pass
This commit is contained in:
@@ -155,24 +155,32 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
/// If you're unsure what that means, it likely does not apply to you.
|
/// If you're unsure what that means, it likely does not apply to you.
|
||||||
/// This invariant will be enforced in the future.
|
/// This invariant will be enforced in the future.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn deref(self, memory: &Memory, index: u32, length: u32) -> Option<&[Cell<T>]> {
|
pub fn deref(self, memory: &Memory, index: u32, length: u32) -> Option<Box<[WasmCell<T>]>> {
|
||||||
// gets the size of the item in the array with padding added such that
|
// gets the size of the item in the array with padding added such that
|
||||||
// for any index, we will always result an aligned memory access
|
// for any index, we will always result an aligned memory access
|
||||||
let item_size = mem::size_of::<T>();
|
let item_size = mem::size_of::<T>() as u32;
|
||||||
let slice_full_len = index as usize + length as usize;
|
let slice_full_len = index + length;
|
||||||
let memory_size = memory.size().bytes().0;
|
let memory_size = memory.size().bytes().0 as u32;
|
||||||
|
|
||||||
if (self.offset as usize) + (item_size * slice_full_len) > memory_size
|
if self.offset + (item_size * slice_full_len) > memory_size
|
||||||
|| self.offset as usize >= memory_size
|
|| self.offset >= memory_size
|
||||||
|| mem::size_of::<T>() == 0
|
|| item_size == 0
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// let subarray = &memory.uint8view().subarray(self.offset, total_len as u32);
|
|
||||||
// let subarray_static = unsafe { std::mem::transmute::<&js_sys::Uint8Array, &'static js_sys::Uint8Array>(&subarray) };
|
|
||||||
// Some(WasmCell::new(subarray_static))
|
|
||||||
|
|
||||||
unimplemented!();
|
Some(
|
||||||
|
(0..length)
|
||||||
|
.map(|i| {
|
||||||
|
let subarray = memory.uint8view().subarray(
|
||||||
|
self.offset + i * item_size,
|
||||||
|
self.offset + (i + 1) * item_size,
|
||||||
|
);
|
||||||
|
WasmCell::new(subarray)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_boxed_slice(),
|
||||||
|
)
|
||||||
// unsafe {
|
// unsafe {
|
||||||
// let cell_ptr = align_pointer(
|
// let cell_ptr = align_pointer(
|
||||||
// memory.view::<u8>().as_ptr().add(self.offset as usize) as usize,
|
// memory.view::<u8>().as_ptr().add(self.offset as usize) as usize,
|
||||||
@@ -197,8 +205,8 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
memory: &Memory,
|
memory: &Memory,
|
||||||
index: u32,
|
index: u32,
|
||||||
length: u32,
|
length: u32,
|
||||||
) -> Option<&mut [Cell<T>]> {
|
) -> Option<Box<[WasmCell<T>]>> {
|
||||||
unimplemented!();
|
self.deref(memory, index, length)
|
||||||
// // gets the size of the item in the array with padding added such that
|
// // gets the size of the item in the array with padding added such that
|
||||||
// // for any index, we will always result an aligned memory access
|
// // for any index, we will always result an aligned memory access
|
||||||
// let item_size = mem::size_of::<T>();
|
// let item_size = mem::size_of::<T>();
|
||||||
@@ -238,7 +246,11 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
///
|
///
|
||||||
/// Additionally, if `memory` is dynamic, the caller must also ensure that `memory`
|
/// Additionally, if `memory` is dynamic, the caller must also ensure that `memory`
|
||||||
/// is not grown while the reference is held.
|
/// is not grown while the reference is held.
|
||||||
pub unsafe fn get_utf8_str<'a>(self, memory: &'a Memory, str_len: u32) -> Option<&'a str> {
|
pub unsafe fn get_utf8_str<'a>(
|
||||||
|
self,
|
||||||
|
memory: &'a Memory,
|
||||||
|
str_len: u32,
|
||||||
|
) -> Option<std::borrow::Cow<'a, str>> {
|
||||||
let memory_size = memory.size().bytes().0;
|
let memory_size = memory.size().bytes().0;
|
||||||
|
|
||||||
if self.offset as usize + str_len as usize > memory.size().bytes().0
|
if self.offset as usize + str_len as usize > memory.size().bytes().0
|
||||||
@@ -246,9 +258,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ptr = memory.view::<u8>().as_ptr().add(self.offset as usize) as *const u8;
|
let subarray = memory.uint8view().subarray(self.offset, str_len).to_vec();
|
||||||
let slice: &[u8] = std::slice::from_raw_parts(ptr, str_len as usize);
|
// std::str::from_utf8(subarray.as_slice()).ok()
|
||||||
std::str::from_utf8(slice).ok()
|
String::from_utf8(subarray).ok().map(std::borrow::Cow::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a UTF-8 `String` from the `WasmPtr` with the given length.
|
/// Get a UTF-8 `String` from the `WasmPtr` with the given length.
|
||||||
@@ -262,42 +274,8 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: benchmark the internals of this function: there is likely room for
|
let subarray = memory.uint8view().subarray(self.offset, str_len).to_vec();
|
||||||
// micro-optimization here and this may be a fairly common function in user code.
|
String::from_utf8(subarray).ok()
|
||||||
let view = memory.view::<u8>();
|
|
||||||
|
|
||||||
let mut vec: Vec<u8> = Vec::with_capacity(str_len as usize);
|
|
||||||
let base = self.offset as usize;
|
|
||||||
for i in 0..(str_len as usize) {
|
|
||||||
let byte = view[base + i].get();
|
|
||||||
vec.push(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
String::from_utf8(vec).ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a UTF-8 string from the `WasmPtr`, where the string is nul-terminated.
|
|
||||||
///
|
|
||||||
/// Note that this does not account for UTF-8 strings that _contain_ nul themselves,
|
|
||||||
/// [`WasmPtr::get_utf8_str`] has to be used for those.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// This method behaves similarly to [`WasmPtr::get_utf8_str`], all safety invariants on
|
|
||||||
/// that method must also be upheld here.
|
|
||||||
pub unsafe fn get_utf8_str_with_nul<'a>(self, memory: &'a Memory) -> Option<&'a str> {
|
|
||||||
memory.view::<u8>()[(self.offset as usize)..]
|
|
||||||
.iter()
|
|
||||||
.map(|cell| cell.get())
|
|
||||||
.position(|byte| byte == 0)
|
|
||||||
.and_then(|length| self.get_utf8_str(memory, length as u32))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a UTF-8 `String` from the `WasmPtr`, where the string is nul-terminated.
|
|
||||||
///
|
|
||||||
/// Note that this does not account for UTF-8 strings that _contain_ nul themselves,
|
|
||||||
/// [`WasmPtr::get_utf8_string`] has to be used for those.
|
|
||||||
pub fn get_utf8_string_with_nul(self, memory: &Memory) -> Option<String> {
|
|
||||||
unsafe { self.get_utf8_str_with_nul(memory) }.map(|s| s.to_owned())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,16 +364,16 @@ mod test {
|
|||||||
|
|
||||||
// test that basic access works and that len = 0 works, but oob does not
|
// test that basic access works and that len = 0 works, but oob does not
|
||||||
let start_wasm_ptr: WasmPtr<u8> = WasmPtr::new(0);
|
let start_wasm_ptr: WasmPtr<u8> = WasmPtr::new(0);
|
||||||
// let start_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(0);
|
let start_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(0);
|
||||||
|
|
||||||
assert!(start_wasm_ptr.deref(&memory).is_some());
|
assert!(start_wasm_ptr.deref(&memory).is_some());
|
||||||
assert!(unsafe { start_wasm_ptr.deref_mut(&memory).is_some() });
|
assert!(unsafe { start_wasm_ptr.deref_mut(&memory).is_some() });
|
||||||
// assert!(start_wasm_ptr_array.deref(&memory, 0, 0).is_some());
|
assert!(start_wasm_ptr_array.deref(&memory, 0, 0).is_some());
|
||||||
// assert!(unsafe { start_wasm_ptr_array.get_utf8_str(&memory, 0).is_some() });
|
assert!(unsafe { start_wasm_ptr_array.get_utf8_str(&memory, 0).is_some() });
|
||||||
// assert!(start_wasm_ptr_array.get_utf8_string(&memory, 0).is_some());
|
assert!(start_wasm_ptr_array.get_utf8_string(&memory, 0).is_some());
|
||||||
// assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 0).is_some() });
|
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 0).is_some() });
|
||||||
// assert!(start_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
assert!(start_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||||
// assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||||
|
|
||||||
// test that accessing the last valid memory address works correctly and OOB is caught
|
// test that accessing the last valid memory address works correctly and OOB is caught
|
||||||
let last_valid_address_for_u8 = (memory.size().bytes().0 - 1) as u32;
|
let last_valid_address_for_u8 = (memory.size().bytes().0 - 1) as u32;
|
||||||
@@ -403,18 +381,18 @@ mod test {
|
|||||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||||
|
|
||||||
// let end_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(last_valid_address_for_u8);
|
let end_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(last_valid_address_for_u8);
|
||||||
|
|
||||||
// assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||||
// assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||||
// let invalid_idx_len_combos: [(u32, u32); 3] =
|
let invalid_idx_len_combos: [(u32, u32); 3] =
|
||||||
// [(last_valid_address_for_u8 + 1, 0), (0, 2), (1, 1)];
|
[(last_valid_address_for_u8 + 1, 0), (0, 2), (1, 1)];
|
||||||
// for &(idx, len) in invalid_idx_len_combos.iter() {
|
for &(idx, len) in invalid_idx_len_combos.iter() {
|
||||||
// assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||||
// assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||||
// }
|
}
|
||||||
// assert!(unsafe { end_wasm_ptr_array.get_utf8_str(&memory, 2).is_none() });
|
assert!(unsafe { end_wasm_ptr_array.get_utf8_str(&memory, 2).is_none() });
|
||||||
// assert!(end_wasm_ptr_array.get_utf8_string(&memory, 2).is_none());
|
assert!(end_wasm_ptr_array.get_utf8_string(&memory, 2).is_none());
|
||||||
|
|
||||||
// test that accesing the last valid memory address for a u32 is valid
|
// test that accesing the last valid memory address for a u32 is valid
|
||||||
// (same as above test but with more edge cases to assert on)
|
// (same as above test but with more edge cases to assert on)
|
||||||
@@ -435,29 +413,29 @@ mod test {
|
|||||||
assert!(oob_end_ptr.deref(&memory).is_none());
|
assert!(oob_end_ptr.deref(&memory).is_none());
|
||||||
assert!(unsafe { oob_end_ptr.deref_mut(&memory).is_none() });
|
assert!(unsafe { oob_end_ptr.deref_mut(&memory).is_none() });
|
||||||
}
|
}
|
||||||
// let end_wasm_ptr_array: WasmPtr<u32, Array> = WasmPtr::new(last_valid_address_for_u32);
|
let end_wasm_ptr_array: WasmPtr<u32, Array> = WasmPtr::new(last_valid_address_for_u32);
|
||||||
// assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||||
// assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||||
|
|
||||||
// let invalid_idx_len_combos: [(u32, u32); 3] =
|
let invalid_idx_len_combos: [(u32, u32); 3] =
|
||||||
// [(last_valid_address_for_u32 + 1, 0), (0, 2), (1, 1)];
|
[(last_valid_address_for_u32 + 1, 0), (0, 2), (1, 1)];
|
||||||
// for &(idx, len) in invalid_idx_len_combos.iter() {
|
for &(idx, len) in invalid_idx_len_combos.iter() {
|
||||||
// assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||||
// assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let end_wasm_ptr_array_oob_array: [WasmPtr<u32, Array>; 4] = [
|
let end_wasm_ptr_array_oob_array: [WasmPtr<u32, Array>; 4] = [
|
||||||
// WasmPtr::new(last_valid_address_for_u32 + 1),
|
WasmPtr::new(last_valid_address_for_u32 + 1),
|
||||||
// WasmPtr::new(last_valid_address_for_u32 + 2),
|
WasmPtr::new(last_valid_address_for_u32 + 2),
|
||||||
// WasmPtr::new(last_valid_address_for_u32 + 3),
|
WasmPtr::new(last_valid_address_for_u32 + 3),
|
||||||
// WasmPtr::new(last_valid_address_for_u32 + 4),
|
WasmPtr::new(last_valid_address_for_u32 + 4),
|
||||||
// ];
|
];
|
||||||
|
|
||||||
// for oob_end_array_ptr in end_wasm_ptr_array_oob_array.iter() {
|
for oob_end_array_ptr in end_wasm_ptr_array_oob_array.iter() {
|
||||||
// assert!(oob_end_array_ptr.deref(&memory, 0, 1).is_none());
|
assert!(oob_end_array_ptr.deref(&memory, 0, 1).is_none());
|
||||||
// assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 1).is_none() });
|
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 1).is_none() });
|
||||||
// assert!(oob_end_array_ptr.deref(&memory, 1, 0).is_none());
|
assert!(oob_end_array_ptr.deref(&memory, 1, 0).is_none());
|
||||||
// assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 1, 0).is_none() });
|
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 1, 0).is_none() });
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user