mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Create a grow error and refactor grow impl to return result (#191)
This commit is contained in:
parent
fa596d2d23
commit
82eef13f41
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1197,7 +1197,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmer"
|
||||
version = "0.1.4"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -208,14 +208,13 @@ pub extern "C" fn wasmer_memory_grow(
|
||||
delta: uint32_t,
|
||||
) -> wasmer_result_t {
|
||||
let memory = unsafe { &*(memory as *mut Memory) };
|
||||
let maybe_delta = memory.grow(Pages(delta));
|
||||
if let Some(_delta) = maybe_delta {
|
||||
wasmer_result_t::WASMER_OK
|
||||
} else {
|
||||
update_last_error(CApiError {
|
||||
msg: "unable to grow memory".to_string(),
|
||||
});
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
let delta_result = memory.grow(Pages(delta));
|
||||
match delta_result {
|
||||
Ok(_) => wasmer_result_t::WASMER_OK,
|
||||
Err(grow_error) => {
|
||||
update_last_error(grow_error);
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,14 +276,13 @@ pub extern "C" fn wasmer_table_grow(
|
||||
delta: uint32_t,
|
||||
) -> wasmer_result_t {
|
||||
let table = unsafe { &*(table as *mut Table) };
|
||||
let maybe_delta = table.grow(delta);
|
||||
if let Some(_delta) = maybe_delta {
|
||||
wasmer_result_t::WASMER_OK
|
||||
} else {
|
||||
update_last_error(CApiError {
|
||||
msg: "unable to grow table".to_string(),
|
||||
});
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
let delta_result = table.grow(delta);
|
||||
match delta_result {
|
||||
Ok(_) => wasmer_result_t::WASMER_OK,
|
||||
Err(grow_error) => {
|
||||
update_last_error(grow_error);
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,13 +23,13 @@ int main()
|
||||
wasmer_result_t grow_result = wasmer_memory_grow(memory, 2);
|
||||
assert(grow_result == WASMER_OK);
|
||||
|
||||
uint32_t new_len = wasmer_memory_length(memory);
|
||||
uint32_t new_len = wasmer_memory_length(memory);
|
||||
printf("Memory pages length: %d\n", new_len);
|
||||
assert(new_len == 12);
|
||||
|
||||
uint32_t bytes_len = wasmer_memory_data_length(memory);
|
||||
uint32_t bytes_len = wasmer_memory_data_length(memory);
|
||||
printf("Memory bytes length: %d\n", bytes_len);
|
||||
assert(bytes_len == 12 * 65536);
|
||||
assert(bytes_len == 12 * 65536);
|
||||
|
||||
// Err, grow beyond max
|
||||
wasmer_result_t grow_result2 = wasmer_memory_grow(memory, 10);
|
||||
@ -38,23 +38,26 @@ int main()
|
||||
char *error_str = malloc(error_len);
|
||||
wasmer_last_error_message(error_str, error_len);
|
||||
printf("Error str: `%s`\n", error_str);
|
||||
assert(0 == strcmp(error_str, "unable to grow memory"));
|
||||
assert(0 == strcmp(error_str, "Failed to add pages because would exceed maximum number of pages for the memory. Left: 22, Added: 15"));
|
||||
free(error_str);
|
||||
|
||||
wasmer_memory_t *bad_memory = NULL;
|
||||
wasmer_limits_t bad_descriptor;
|
||||
bad_descriptor.min = 15;
|
||||
wasmer_limit_option_t max2;
|
||||
max2.has_some = true;
|
||||
max2.some = 10;
|
||||
bad_descriptor.max = max2;
|
||||
wasmer_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor);
|
||||
printf("Bad memory result: %d\n", bad_memory_result);
|
||||
assert(bad_memory_result == WASMER_ERROR);
|
||||
|
||||
// wasmer_memory_t *bad_memory = NULL;
|
||||
// wasmer_limits_t bad_descriptor;
|
||||
// bad_descriptor.min = 15;
|
||||
// bad_descriptor.max = 10;
|
||||
// wasmer_result_t bad_memory_result = wasmer_memory_new(&bad_memory, bad_descriptor);
|
||||
// printf("Bad memory result: %d\n", bad_memory_result);
|
||||
// assert(memory_result == WASMER_MEMORY_ERROR);
|
||||
//
|
||||
// int error_len = wasmer_last_error_length();
|
||||
// char *error_str = malloc(error_len);
|
||||
// wasmer_last_error_message(error_str, error_len);
|
||||
// assert(0 == strcmp(error_str, "Creation error"));
|
||||
// free(error_str);
|
||||
int error_len2 = wasmer_last_error_length();
|
||||
char *error_str2 = malloc(error_len2);
|
||||
wasmer_last_error_message(error_str2, error_len2);
|
||||
printf("Error str 2: `%s`\n", error_str2);
|
||||
assert(0 == strcmp(error_str2, "Unable to create because the supplied descriptor is invalid: \"Max number of memory pages is less than the minimum number of pages\""));
|
||||
free(error_str2);
|
||||
|
||||
printf("Destroy memory\n");
|
||||
wasmer_memory_destroy(memory);
|
||||
|
@ -9,7 +9,7 @@ int main()
|
||||
wasmer_limits_t descriptor;
|
||||
descriptor.min = 10;
|
||||
wasmer_limit_option_t max;
|
||||
// max.has_some = false;
|
||||
// max.has_some = false;
|
||||
max.has_some = true;
|
||||
max.some = 15;
|
||||
descriptor.max = max;
|
||||
@ -21,26 +21,29 @@ int main()
|
||||
printf("Table length: %d\n", len);
|
||||
assert(len == 10);
|
||||
|
||||
// wasmer_result_t grow_result1 = wasmer_table_grow(table, 5);
|
||||
// assert(grow_result1 == WASMER_OK);
|
||||
// uint32_t len_grow1 = wasmer_table_length(table);
|
||||
// printf("Table length: %d\n", len_grow1);
|
||||
// assert(len_grow1 == 15);
|
||||
wasmer_result_t grow_result1 = wasmer_table_grow(table, 5);
|
||||
assert(grow_result1 == WASMER_OK);
|
||||
uint32_t len_grow1 = wasmer_table_length(table);
|
||||
printf("Table length: %d\n", len_grow1);
|
||||
assert(len_grow1 == 15);
|
||||
|
||||
// // Try to grow beyond max
|
||||
// wasmer_result_t grow_result2 = wasmer_table_grow(&table, 1);
|
||||
// assert(grow_result2 == WASMER_ERROR);
|
||||
// uint32_t len_grow2 = wasmer_table_length(table);
|
||||
// printf("Table length: %d\n", len_grow2);
|
||||
// assert(len_grow2 == 15);
|
||||
// Try to grow beyond max
|
||||
wasmer_result_t grow_result2 = wasmer_table_grow(table, 1);
|
||||
assert(grow_result2 == WASMER_ERROR);
|
||||
uint32_t len_grow2 = wasmer_table_length(table);
|
||||
printf("Table length: %d\n", len_grow2);
|
||||
assert(len_grow2 == 15);
|
||||
|
||||
// wasmer_table_t *table_bad = NULL;
|
||||
// wasmer_limits_t bad_descriptor;
|
||||
// bad_descriptor.min = 15;
|
||||
// bad_descriptor.max = 10;
|
||||
// wasmer_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor);
|
||||
// printf("Table result: %d\n", table_bad_result);
|
||||
// assert(table_result == WASMER_ERROR);
|
||||
wasmer_table_t *table_bad = NULL;
|
||||
wasmer_limits_t bad_descriptor;
|
||||
bad_descriptor.min = 15;
|
||||
wasmer_limit_option_t max2;
|
||||
max2.has_some = true;
|
||||
max2.some = 10;
|
||||
bad_descriptor.max = max2;
|
||||
wasmer_result_t table_bad_result = wasmer_table_new(&table_bad, bad_descriptor);
|
||||
printf("Table result: %d\n", table_bad_result);
|
||||
assert(table_bad_result == WASMER_ERROR);
|
||||
|
||||
printf("Destroy table\n");
|
||||
wasmer_table_destroy(table);
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::sys::Memory;
|
||||
use crate::types::{
|
||||
FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type,
|
||||
};
|
||||
@ -369,3 +370,105 @@ impl std::fmt::Display for Error {
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GrowError {
|
||||
MemoryGrowError,
|
||||
TableGrowError,
|
||||
ExceededMaxPages(PageError),
|
||||
ExceededMaxPagesForMemory(usize, usize),
|
||||
CouldNotProtectMemory(MemoryProtectionError),
|
||||
CouldNotCreateMemory(MemoryCreationError),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GrowError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
GrowError::MemoryGrowError => write!(f, "Unable to grow memory"),
|
||||
GrowError::TableGrowError => write!(f, "Unable to grow table"),
|
||||
GrowError::ExceededMaxPages(e) => write!(f, "Grow Error: {}", e),
|
||||
GrowError::ExceededMaxPagesForMemory(left, added) => write!(f, "Failed to add pages because would exceed maximum number of pages for the memory. Left: {}, Added: {}", left, added),
|
||||
GrowError::CouldNotCreateMemory(e) => write!(f, "Grow Error: {}", e),
|
||||
GrowError::CouldNotProtectMemory(e) => write!(f, "Grow Error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for GrowError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PageError {
|
||||
// left, right, added
|
||||
ExceededMaxPages(usize, usize, usize),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PageError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
PageError::ExceededMaxPages(left, right, added) => write!(f, "Failed to add pages because would exceed maximum number of pages. Left: {}, Right: {}, Pages added: {}", left, right, added),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for PageError {}
|
||||
|
||||
impl Into<GrowError> for PageError {
|
||||
fn into(self) -> GrowError {
|
||||
GrowError::ExceededMaxPages(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MemoryCreationError {
|
||||
VirtualMemoryAllocationFailed(usize, String),
|
||||
CouldNotCreateMemoryFromFile(std::io::Error),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MemoryCreationError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
MemoryCreationError::VirtualMemoryAllocationFailed(size, msg) => write!(
|
||||
f,
|
||||
"Allocation virtual memory with size {} failed. \nErrno message: {}",
|
||||
size, msg
|
||||
),
|
||||
MemoryCreationError::CouldNotCreateMemoryFromFile(e) => write!(f, "IO Error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for MemoryCreationError {}
|
||||
|
||||
impl Into<GrowError> for MemoryCreationError {
|
||||
fn into(self) -> GrowError {
|
||||
GrowError::CouldNotCreateMemory(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for MemoryCreationError {
|
||||
fn from(io_error: std::io::Error) -> Self {
|
||||
MemoryCreationError::CouldNotCreateMemoryFromFile(io_error)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MemoryProtectionError {
|
||||
ProtectionFailed(usize, usize, String),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MemoryProtectionError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
MemoryProtectionError::ProtectionFailed(start, size, msg) => write!(
|
||||
f,
|
||||
"Allocation virtual memory starting at {} with size {} failed. \nErrno message: {}",
|
||||
start, size, msg
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for MemoryProtectionError {}
|
||||
|
||||
impl Into<GrowError> for MemoryProtectionError {
|
||||
fn into(self) -> GrowError {
|
||||
GrowError::CouldNotProtectMemory(self)
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::error::GrowError;
|
||||
use crate::{
|
||||
error::CreationError,
|
||||
sys,
|
||||
@ -14,9 +15,9 @@ pub const DYNAMIC_GUARD_SIZE: usize = 4096;
|
||||
/// when first created. Over time, as it grows, it may reallocate to
|
||||
/// a different location and size.
|
||||
///
|
||||
/// Dynamic memories are signifigantly faster to create than static
|
||||
/// Dynamic memories are significantly faster to create than static
|
||||
/// memories and use much less virtual memory, however, they require
|
||||
/// the webassembly module to bounds-check memory accesses.
|
||||
/// the WebAssembly module to bounds-check memory accesses.
|
||||
///
|
||||
/// While, a dynamic memory could use a vector of some sort as its
|
||||
/// backing memory, we use mmap (or the platform-equivalent) to allow
|
||||
@ -65,26 +66,29 @@ impl DynamicMemory {
|
||||
self.current
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option<Pages> {
|
||||
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Result<Pages, GrowError> {
|
||||
if delta == Pages(0) {
|
||||
return Some(self.current);
|
||||
return Ok(self.current);
|
||||
}
|
||||
|
||||
let new_pages = self.current.checked_add(delta)?;
|
||||
let new_pages = self.current.checked_add(delta).map_err(|e| e.into())?;
|
||||
|
||||
if let Some(max) = self.max {
|
||||
if new_pages > max {
|
||||
return None;
|
||||
return Err(GrowError::ExceededMaxPagesForMemory(
|
||||
new_pages.0 as usize,
|
||||
max.0 as usize,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut new_memory =
|
||||
sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE).ok()?;
|
||||
let mut new_memory = sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE)
|
||||
.map_err(|e| e.into())?;
|
||||
|
||||
unsafe {
|
||||
new_memory
|
||||
.protect(0..new_pages.bytes().0, sys::Protect::ReadWrite)
|
||||
.ok()?;
|
||||
.map_err(|e| e.into())?;
|
||||
|
||||
new_memory.as_slice_mut()[..self.current.bytes().0]
|
||||
.copy_from_slice(&self.memory.as_slice()[..self.current.bytes().0]);
|
||||
@ -97,7 +101,7 @@ impl DynamicMemory {
|
||||
|
||||
let old_pages = self.current;
|
||||
self.current = new_pages;
|
||||
Some(old_pages)
|
||||
Ok(old_pages)
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
error::CreationError,
|
||||
error::{CreationError, GrowError},
|
||||
export::Export,
|
||||
import::IsExport,
|
||||
memory::dynamic::DYNAMIC_GUARD_SIZE,
|
||||
@ -89,8 +89,8 @@ impl Memory {
|
||||
self.desc
|
||||
}
|
||||
|
||||
/// Grow this memory by the specfied number of pages.
|
||||
pub fn grow(&self, delta: Pages) -> Option<Pages> {
|
||||
/// Grow this memory by the specified number of pages.
|
||||
pub fn grow(&self, delta: Pages) -> Result<Pages, GrowError> {
|
||||
match &self.variant {
|
||||
MemoryVariant::Unshared(unshared_mem) => unshared_mem.grow(delta),
|
||||
MemoryVariant::Shared(shared_mem) => shared_mem.grow(delta),
|
||||
@ -244,7 +244,7 @@ impl UnsharedMemory {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn grow(&self, delta: Pages) -> Option<Pages> {
|
||||
pub fn grow(&self, delta: Pages) -> Result<Pages, GrowError> {
|
||||
let mut storage = self.internal.storage.borrow_mut();
|
||||
|
||||
let mut local = self.internal.local.get();
|
||||
@ -292,7 +292,7 @@ impl SharedMemory {
|
||||
Ok(Self { desc })
|
||||
}
|
||||
|
||||
pub fn grow(&self, _delta: Pages) -> Option<Pages> {
|
||||
pub fn grow(&self, _delta: Pages) -> Result<Pages, GrowError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::error::GrowError;
|
||||
use crate::{
|
||||
error::CreationError,
|
||||
memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE},
|
||||
@ -61,27 +62,30 @@ impl StaticMemory {
|
||||
self.current
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option<Pages> {
|
||||
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Result<Pages, GrowError> {
|
||||
if delta == Pages(0) {
|
||||
return Some(self.current);
|
||||
return Ok(self.current);
|
||||
}
|
||||
|
||||
let new_pages = self.current.checked_add(delta)?;
|
||||
let new_pages = self.current.checked_add(delta).map_err(|e| e.into())?;
|
||||
|
||||
if let Some(max) = self.max {
|
||||
if new_pages > max {
|
||||
return None;
|
||||
return Err(GrowError::ExceededMaxPagesForMemory(
|
||||
new_pages.0 as usize,
|
||||
max.0 as usize,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let _ = unsafe {
|
||||
self.memory
|
||||
.protect(
|
||||
self.current.bytes().0..new_pages.bytes().0,
|
||||
sys::Protect::ReadWrite,
|
||||
)
|
||||
.ok()?;
|
||||
}
|
||||
.map_err(|e| e.into())
|
||||
}?;
|
||||
|
||||
local.bound = new_pages.bytes().0;
|
||||
|
||||
@ -89,7 +93,7 @@ impl StaticMemory {
|
||||
|
||||
self.current = new_pages;
|
||||
|
||||
Some(old_pages)
|
||||
Ok(old_pages)
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::error::MemoryCreationError;
|
||||
use crate::error::MemoryProtectionError;
|
||||
use errno;
|
||||
use nix::libc;
|
||||
use page_size;
|
||||
@ -16,13 +18,13 @@ pub struct Memory {
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub fn from_file_path<P>(path: P, protection: Protect) -> Result<Self, String>
|
||||
pub fn from_file_path<P>(path: P, protection: Protect) -> Result<Self, MemoryCreationError>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let file = File::open(path).map_err(|e| e.to_string())?;
|
||||
let file = File::open(path)?;
|
||||
|
||||
let file_len = file.metadata().map_err(|e| e.to_string())?.len();
|
||||
let file_len = file.metadata()?.len();
|
||||
|
||||
let raw_fd = RawFd::from_file(file);
|
||||
|
||||
@ -38,7 +40,10 @@ impl Memory {
|
||||
};
|
||||
|
||||
if ptr == -1 as _ {
|
||||
Err(errno::errno().to_string())
|
||||
Err(MemoryCreationError::VirtualMemoryAllocationFailed(
|
||||
file_len as usize,
|
||||
errno::errno().to_string(),
|
||||
))
|
||||
} else {
|
||||
Ok(Self {
|
||||
ptr: ptr as *mut u8,
|
||||
@ -84,7 +89,7 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_size(size: usize) -> Result<Self, String> {
|
||||
pub fn with_size(size: usize) -> Result<Self, MemoryCreationError> {
|
||||
if size == 0 {
|
||||
return Ok(Self {
|
||||
ptr: ptr::null_mut(),
|
||||
@ -108,7 +113,10 @@ impl Memory {
|
||||
};
|
||||
|
||||
if ptr == -1 as _ {
|
||||
Err(errno::errno().to_string())
|
||||
Err(MemoryCreationError::VirtualMemoryAllocationFailed(
|
||||
size,
|
||||
errno::errno().to_string(),
|
||||
))
|
||||
} else {
|
||||
Ok(Self {
|
||||
ptr: ptr as *mut u8,
|
||||
@ -123,7 +131,7 @@ impl Memory {
|
||||
&mut self,
|
||||
range: impl RangeBounds<usize>,
|
||||
protection: Protect,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<(), MemoryProtectionError> {
|
||||
let protect = protection.to_protect_const();
|
||||
|
||||
let range_start = match range.start_bound() {
|
||||
@ -147,7 +155,11 @@ impl Memory {
|
||||
|
||||
let success = libc::mprotect(start as _, size, protect as i32);
|
||||
if success == -1 {
|
||||
Err(errno::errno().to_string())
|
||||
Err(MemoryProtectionError::ProtectionFailed(
|
||||
start as usize,
|
||||
size,
|
||||
errno::errno().to_string(),
|
||||
))
|
||||
} else {
|
||||
self.protection = protection;
|
||||
Ok(())
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::error::MemoryCreationError;
|
||||
use crate::error::MemoryProtectionError;
|
||||
use page_size;
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
use std::{ptr, slice};
|
||||
@ -44,7 +46,7 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_size(size: usize) -> Result<Self, String> {
|
||||
pub fn with_size(size: usize) -> Result<Self, MemoryCreationError> {
|
||||
if size == 0 {
|
||||
return Ok(Self {
|
||||
ptr: ptr::null_mut(),
|
||||
@ -58,7 +60,10 @@ impl Memory {
|
||||
let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, PAGE_NOACCESS) };
|
||||
|
||||
if ptr.is_null() {
|
||||
Err("unable to allocate memory".to_string())
|
||||
Err(MemoryCreationError::VirtualMemoryAllocationFailed(
|
||||
size,
|
||||
"unable to allocate memory".to_string(),
|
||||
))
|
||||
} else {
|
||||
Ok(Self {
|
||||
ptr: ptr as *mut u8,
|
||||
@ -72,7 +77,7 @@ impl Memory {
|
||||
&mut self,
|
||||
range: impl RangeBounds<usize>,
|
||||
protect: Protect,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<(), MemoryProtectionError> {
|
||||
let protect_const = protect.to_protect_const();
|
||||
|
||||
let range_start = match range.start_bound() {
|
||||
@ -98,7 +103,11 @@ impl Memory {
|
||||
let ptr = VirtualAlloc(start as _, size, MEM_COMMIT, protect_const);
|
||||
|
||||
if ptr.is_null() {
|
||||
Err("unable to protect memory".to_string())
|
||||
Err(MemoryProtectionError::ProtectionFailed(
|
||||
start as usize,
|
||||
size,
|
||||
"unable to protect memory".to_string(),
|
||||
))
|
||||
} else {
|
||||
self.protection = protect;
|
||||
Ok(())
|
||||
|
@ -11,6 +11,7 @@ mod anyfunc;
|
||||
|
||||
pub use self::anyfunc::Anyfunc;
|
||||
use self::anyfunc::AnyfuncTable;
|
||||
use crate::error::GrowError;
|
||||
|
||||
pub enum Element<'a> {
|
||||
Anyfunc(Anyfunc<'a>),
|
||||
@ -108,15 +109,15 @@ impl Table {
|
||||
}
|
||||
|
||||
/// Grow this table by `delta`.
|
||||
pub fn grow(&self, delta: u32) -> Option<u32> {
|
||||
pub fn grow(&self, delta: u32) -> Result<u32, GrowError> {
|
||||
if delta == 0 {
|
||||
return Some(self.size());
|
||||
return Ok(self.size());
|
||||
}
|
||||
|
||||
match &mut *self.storage.borrow_mut() {
|
||||
(TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => {
|
||||
anyfunc_table.grow(delta, local)
|
||||
}
|
||||
(TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => anyfunc_table
|
||||
.grow(delta, local)
|
||||
.ok_or(GrowError::TableGrowError),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::error::PageError;
|
||||
use std::{
|
||||
fmt,
|
||||
ops::{Add, Sub},
|
||||
@ -11,12 +12,16 @@ const WASM_MAX_PAGES: usize = 65_536;
|
||||
pub struct Pages(pub u32);
|
||||
|
||||
impl Pages {
|
||||
pub fn checked_add(self, rhs: Pages) -> Option<Pages> {
|
||||
pub fn checked_add(self, rhs: Pages) -> Result<Pages, PageError> {
|
||||
let added = (self.0 as usize) + (rhs.0 as usize);
|
||||
if added <= WASM_MAX_PAGES {
|
||||
Some(Pages(added as u32))
|
||||
Ok(Pages(added as u32))
|
||||
} else {
|
||||
None
|
||||
Err(PageError::ExceededMaxPages(
|
||||
self.0 as usize,
|
||||
rhs.0 as usize,
|
||||
added,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,9 @@ pub unsafe extern "C" fn local_static_memory_grow(
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||
old.0 as i32
|
||||
} else {
|
||||
-1
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,10 +44,9 @@ pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||
old.0 as i32
|
||||
} else {
|
||||
-1
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,10 +72,9 @@ pub unsafe extern "C" fn imported_static_memory_grow(
|
||||
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||
old.0 as i32
|
||||
} else {
|
||||
-1
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,10 +96,9 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow(
|
||||
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
|
||||
old.0 as i32
|
||||
} else {
|
||||
-1
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user