mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 08:57:56 +00:00
Improve Wasm extern errors and increase heap (#299)
* Improve Wasm extern errors * Increase heap size * Update heap size further
This commit is contained in:
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -22,7 +22,7 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use codec::Slicable;
|
||||
use primitives::sandbox as sandbox_primitives;
|
||||
use wasm_utils::DummyUserError;
|
||||
use wasm_utils::UserError;
|
||||
use wasmi;
|
||||
use wasmi::memory_units::Pages;
|
||||
use wasmi::{
|
||||
@@ -161,14 +161,14 @@ pub trait SandboxCapabilities {
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if `ptr + data.len()` is out of bounds.
|
||||
fn write_memory(&mut self, ptr: u32, data: &[u8]) -> Result<(), DummyUserError>;
|
||||
fn write_memory(&mut self, ptr: u32, data: &[u8]) -> Result<(), UserError>;
|
||||
|
||||
/// Read `len` bytes from the supervisor memory.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if `ptr + len` is out of bounds.
|
||||
fn read_memory(&self, ptr: u32, len: u32) -> Result<Vec<u8>, DummyUserError>;
|
||||
fn read_memory(&self, ptr: u32, len: u32) -> Result<Vec<u8>, UserError>;
|
||||
}
|
||||
|
||||
/// Implementation of [`Externals`] that allows execution of guest module with
|
||||
@@ -182,7 +182,7 @@ pub struct GuestExternals<'a, FE: SandboxCapabilities + Externals + 'a> {
|
||||
}
|
||||
|
||||
fn trap() -> Trap {
|
||||
TrapKind::Host(Box::new(DummyUserError)).into()
|
||||
TrapKind::Host(Box::new(UserError("Sandbox error"))).into()
|
||||
}
|
||||
|
||||
fn deserialize_result(serialized_result: &[u8]) -> Result<Option<RuntimeValue>, Trap> {
|
||||
@@ -338,8 +338,8 @@ impl SandboxInstance {
|
||||
fn decode_environment_definition(
|
||||
raw_env_def: &[u8],
|
||||
memories: &[Option<MemoryRef>],
|
||||
) -> Result<(Imports, GuestToSupervisorFunctionMapping), DummyUserError> {
|
||||
let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]).ok_or_else(|| DummyUserError)?;
|
||||
) -> Result<(Imports, GuestToSupervisorFunctionMapping), UserError> {
|
||||
let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]).ok_or_else(|| UserError("Sandbox error"))?;
|
||||
|
||||
let mut func_map = HashMap::new();
|
||||
let mut memories_map = HashMap::new();
|
||||
@@ -359,8 +359,8 @@ fn decode_environment_definition(
|
||||
let memory_ref = memories
|
||||
.get(memory_idx as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| DummyUserError)?
|
||||
.ok_or_else(|| DummyUserError)?;
|
||||
.ok_or_else(|| UserError("Sandbox error"))?
|
||||
.ok_or_else(|| UserError("Sandbox error"))?;
|
||||
memories_map.insert((module, field), memory_ref);
|
||||
}
|
||||
}
|
||||
@@ -395,12 +395,12 @@ pub fn instantiate<FE: SandboxCapabilities + Externals>(
|
||||
wasm: &[u8],
|
||||
raw_env_def: &[u8],
|
||||
state: u32,
|
||||
) -> Result<u32, DummyUserError> {
|
||||
) -> Result<u32, UserError> {
|
||||
let (imports, guest_to_supervisor_mapping) =
|
||||
decode_environment_definition(raw_env_def, &supervisor_externals.store().memories)?;
|
||||
|
||||
let module = Module::from_buffer(wasm).map_err(|_| DummyUserError)?;
|
||||
let instance = ModuleInstance::new(&module, &imports).map_err(|_| DummyUserError)?;
|
||||
let module = Module::from_buffer(wasm).map_err(|_| UserError("Sandbox error"))?;
|
||||
let instance = ModuleInstance::new(&module, &imports).map_err(|_| UserError("Sandbox error"))?;
|
||||
|
||||
let sandbox_instance = Rc::new(SandboxInstance {
|
||||
// In general, it's not a very good idea to use `.not_started_instance()` for anything
|
||||
@@ -418,7 +418,7 @@ pub fn instantiate<FE: SandboxCapabilities + Externals>(
|
||||
|guest_externals| {
|
||||
instance
|
||||
.run_start(guest_externals)
|
||||
.map_err(|_| DummyUserError)
|
||||
.map_err(|_| UserError("Sandbox error"))
|
||||
},
|
||||
)?;
|
||||
|
||||
@@ -451,14 +451,14 @@ impl Store {
|
||||
///
|
||||
/// Returns `Err` if the memory couldn't be created.
|
||||
/// Typically happens if `initial` is more than `maximum`.
|
||||
pub fn new_memory(&mut self, initial: u32, maximum: u32) -> Result<u32, DummyUserError> {
|
||||
pub fn new_memory(&mut self, initial: u32, maximum: u32) -> Result<u32, UserError> {
|
||||
let maximum = match maximum {
|
||||
sandbox_primitives::MEM_UNLIMITED => None,
|
||||
specified_limit => Some(Pages(specified_limit as usize)),
|
||||
};
|
||||
|
||||
let mem =
|
||||
MemoryInstance::alloc(Pages(initial as usize), maximum).map_err(|_| DummyUserError)?;
|
||||
MemoryInstance::alloc(Pages(initial as usize), maximum).map_err(|_| UserError("Sandbox error"))?;
|
||||
let mem_idx = self.memories.len();
|
||||
self.memories.push(Some(mem));
|
||||
Ok(mem_idx as u32)
|
||||
@@ -470,12 +470,12 @@ impl Store {
|
||||
///
|
||||
/// Returns `Err` If `instance_idx` isn't a valid index of an instance or
|
||||
/// instance is already torndown.
|
||||
pub fn instance(&self, instance_idx: u32) -> Result<Rc<SandboxInstance>, DummyUserError> {
|
||||
pub fn instance(&self, instance_idx: u32) -> Result<Rc<SandboxInstance>, UserError> {
|
||||
self.instances
|
||||
.get(instance_idx as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| DummyUserError)?
|
||||
.ok_or_else(|| DummyUserError)
|
||||
.ok_or_else(|| UserError("Sandbox error"))?
|
||||
.ok_or_else(|| UserError("Sandbox error"))
|
||||
}
|
||||
|
||||
/// Returns reference to a memory instance by `memory_idx`.
|
||||
@@ -484,12 +484,12 @@ impl Store {
|
||||
///
|
||||
/// Returns `Err` If `memory_idx` isn't a valid index of an memory or
|
||||
/// memory is already torndown.
|
||||
pub fn memory(&self, memory_idx: u32) -> Result<MemoryRef, DummyUserError> {
|
||||
pub fn memory(&self, memory_idx: u32) -> Result<MemoryRef, UserError> {
|
||||
self.memories
|
||||
.get(memory_idx as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| DummyUserError)?
|
||||
.ok_or_else(|| DummyUserError)
|
||||
.ok_or_else(|| UserError("Sandbox error"))?
|
||||
.ok_or_else(|| UserError("Sandbox error"))
|
||||
}
|
||||
|
||||
/// Teardown the memory at the specified index.
|
||||
@@ -497,18 +497,18 @@ impl Store {
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if `memory_idx` isn't a valid index of an memory.
|
||||
pub fn memory_teardown(&mut self, memory_idx: u32) -> Result<(), DummyUserError> {
|
||||
pub fn memory_teardown(&mut self, memory_idx: u32) -> Result<(), UserError> {
|
||||
if memory_idx as usize >= self.memories.len() {
|
||||
return Err(DummyUserError);
|
||||
return Err(UserError("Sandbox error"));
|
||||
}
|
||||
self.memories[memory_idx as usize] = None;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Teardown the instance at the specified index.
|
||||
pub fn instance_teardown(&mut self, instance_idx: u32) -> Result<(), DummyUserError> {
|
||||
pub fn instance_teardown(&mut self, instance_idx: u32) -> Result<(), UserError> {
|
||||
if instance_idx as usize >= self.instances.len() {
|
||||
return Err(DummyUserError);
|
||||
return Err(UserError("Sandbox error"));
|
||||
}
|
||||
self.instances[instance_idx as usize] = None;
|
||||
Ok(())
|
||||
|
||||
@@ -25,7 +25,7 @@ use wasmi::RuntimeValue::{I32, I64};
|
||||
use wasmi::memory_units::{Pages, Bytes};
|
||||
use state_machine::{Externalities, CodeExecutor};
|
||||
use error::{Error, ErrorKind, Result};
|
||||
use wasm_utils::{DummyUserError};
|
||||
use wasm_utils::UserError;
|
||||
use primitives::{blake2_256, twox_128, twox_256};
|
||||
use primitives::hexdisplay::HexDisplay;
|
||||
use primitives::sandbox as sandbox_primitives;
|
||||
@@ -45,7 +45,7 @@ impl Heap {
|
||||
/// This could mean that wasm binary specifies memory
|
||||
/// limit and we are trying to allocate beyond that limit.
|
||||
fn new(memory: &MemoryRef) -> Result<Self> {
|
||||
const HEAP_SIZE_IN_PAGES: usize = 8;
|
||||
const HEAP_SIZE_IN_PAGES: usize = 1024;
|
||||
|
||||
let prev_page_count = memory
|
||||
.grow(Pages(HEAP_SIZE_IN_PAGES))
|
||||
@@ -98,35 +98,35 @@ impl<'e, E: Externalities> sandbox::SandboxCapabilities for FunctionExecutor<'e,
|
||||
fn deallocate(&mut self, ptr: u32) {
|
||||
self.heap.deallocate(ptr)
|
||||
}
|
||||
fn write_memory(&mut self, ptr: u32, data: &[u8]) -> ::std::result::Result<(), DummyUserError> {
|
||||
self.memory.set(ptr, data).map_err(|_| DummyUserError)
|
||||
fn write_memory(&mut self, ptr: u32, data: &[u8]) -> ::std::result::Result<(), UserError> {
|
||||
self.memory.set(ptr, data).map_err(|_| UserError("Invalid attempt to write_memory"))
|
||||
}
|
||||
fn read_memory(&self, ptr: u32, len: u32) -> ::std::result::Result<Vec<u8>, DummyUserError> {
|
||||
self.memory.get(ptr, len as usize).map_err(|_| DummyUserError)
|
||||
fn read_memory(&self, ptr: u32, len: u32) -> ::std::result::Result<Vec<u8>, UserError> {
|
||||
self.memory.get(ptr, len as usize).map_err(|_| UserError("Invalid attempt to write_memory"))
|
||||
}
|
||||
}
|
||||
|
||||
trait WritePrimitive<T: Sized> {
|
||||
fn write_primitive(&self, offset: u32, t: T) -> ::std::result::Result<(), DummyUserError>;
|
||||
fn write_primitive(&self, offset: u32, t: T) -> ::std::result::Result<(), UserError>;
|
||||
}
|
||||
|
||||
impl WritePrimitive<u32> for MemoryInstance {
|
||||
fn write_primitive(&self, offset: u32, t: u32) -> ::std::result::Result<(), DummyUserError> {
|
||||
fn write_primitive(&self, offset: u32, t: u32) -> ::std::result::Result<(), UserError> {
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
let mut r = [0u8; 4];
|
||||
LittleEndian::write_u32(&mut r, t);
|
||||
self.set(offset, &r).map_err(|_| DummyUserError)
|
||||
self.set(offset, &r).map_err(|_| UserError("Invalid attempt to write_primitive"))
|
||||
}
|
||||
}
|
||||
|
||||
trait ReadPrimitive<T: Sized> {
|
||||
fn read_primitive(&self, offset: u32) -> ::std::result::Result<T, DummyUserError>;
|
||||
fn read_primitive(&self, offset: u32) -> ::std::result::Result<T, UserError>;
|
||||
}
|
||||
|
||||
impl ReadPrimitive<u32> for MemoryInstance {
|
||||
fn read_primitive(&self, offset: u32) -> ::std::result::Result<u32, DummyUserError> {
|
||||
fn read_primitive(&self, offset: u32) -> ::std::result::Result<u32, UserError> {
|
||||
use byteorder::{LittleEndian, ByteOrder};
|
||||
Ok(LittleEndian::read_u32(&self.get(offset, 4).map_err(|_| DummyUserError)?))
|
||||
Ok(LittleEndian::read_u32(&self.get(offset, 4).map_err(|_| UserError("Invalid attempt to read_primitive"))?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,8 +168,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 => {
|
||||
let sl1 = this.memory.get(s1, n as usize).map_err(|_| DummyUserError)?;
|
||||
let sl2 = this.memory.get(s2, n as usize).map_err(|_| DummyUserError)?;
|
||||
let sl1 = this.memory.get(s1, n as usize).map_err(|_| UserError("Invalid attempt to read from memory in first arg of ext_memcmp"))?;
|
||||
let sl2 = this.memory.get(s2, n as usize).map_err(|_| UserError("Invalid attempt to read from memory in second arg of ext_memcmp"))?;
|
||||
Ok(match sl1.cmp(&sl2) {
|
||||
Ordering::Greater => 1,
|
||||
Ordering::Less => -1,
|
||||
@@ -178,20 +178,20 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
},
|
||||
ext_memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => {
|
||||
this.memory.copy_nonoverlapping(src as usize, dest as usize, count as usize)
|
||||
.map_err(|_| DummyUserError)?;
|
||||
.map_err(|_| UserError("Invalid attempt to copy_nonoverlapping in ext_memcpy"))?;
|
||||
trace!(target: "runtime-io", "memcpy {} from {}, {} bytes", dest, src, count);
|
||||
Ok(dest)
|
||||
},
|
||||
ext_memmove(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => {
|
||||
this.memory.copy(src as usize, dest as usize, count as usize)
|
||||
.map_err(|_| DummyUserError)?;
|
||||
.map_err(|_| UserError("Invalid attempt to copy in ext_memmove"))?;
|
||||
trace!(target: "runtime-io", "memmove {} from {}, {} bytes", dest, src, count);
|
||||
Ok(dest)
|
||||
},
|
||||
ext_memset(dest: *mut u8, val: u32, count: usize) -> *mut u8 => {
|
||||
this.memory.clear(dest as usize, val as u8, count as usize)
|
||||
.map_err(|_| DummyUserError)?;
|
||||
trace!(target: "runtime-io", "memset {} with {}, {} bytes", dest, val, count);
|
||||
this.memory.clear(dest as usize, val as u8, count as usize)
|
||||
.map_err(|_| UserError("Invalid attempt to clear in ext_memset"))?;
|
||||
Ok(dest)
|
||||
},
|
||||
ext_malloc(size: usize) -> *mut u8 => {
|
||||
@@ -205,8 +205,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
|
||||
let value = this.memory.get(value_data, value_len as usize).map_err(|_| DummyUserError)?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_storage"))?;
|
||||
let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_storage"))?;
|
||||
if let Some(preimage) = this.hash_lookup.get(&key) {
|
||||
trace!(target: "wasm-trace", "*** Setting storage: %{} -> {} [k={}]", ascii_format(&preimage), HexDisplay::from(&value), HexDisplay::from(&key));
|
||||
} else {
|
||||
@@ -216,7 +216,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_clear_storage(key_data: *const u8, key_len: u32) => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?;
|
||||
if let Some(preimage) = this.hash_lookup.get(&key) {
|
||||
trace!(target: "wasm-trace", "*** Clearing storage: %{} [k={}]", ascii_format(&preimage), HexDisplay::from(&key));
|
||||
} else {
|
||||
@@ -226,13 +226,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
Ok(())
|
||||
},
|
||||
ext_clear_prefix(prefix_data: *const u8, prefix_len: u32) => {
|
||||
let prefix = this.memory.get(prefix_data, prefix_len as usize).map_err(|_| DummyUserError)?;
|
||||
let prefix = this.memory.get(prefix_data, prefix_len as usize).map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?;
|
||||
this.ext.clear_prefix(&prefix);
|
||||
Ok(())
|
||||
},
|
||||
// return 0 and place u32::max_value() into written_out if no value exists for the key.
|
||||
ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_get_allocated_storage"))?;
|
||||
let maybe_value = this.ext.storage(&key);
|
||||
|
||||
if let Some(preimage) = this.hash_lookup.get(&key) {
|
||||
@@ -243,17 +243,19 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
|
||||
if let Some(value) = maybe_value {
|
||||
let offset = this.heap.allocate(value.len() as u32) as u32;
|
||||
this.memory.set(offset, &value).map_err(|_| DummyUserError)?;
|
||||
this.memory.write_primitive(written_out, value.len() as u32)?;
|
||||
this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?;
|
||||
this.memory.write_primitive(written_out, value.len() as u32)
|
||||
.map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_storage"))?;
|
||||
Ok(offset)
|
||||
} else {
|
||||
this.memory.write_primitive(written_out, u32::max_value())?;
|
||||
this.memory.write_primitive(written_out, u32::max_value())
|
||||
.map_err(|_| UserError("Invalid attempt to write failed written_out in ext_get_allocated_storage"))?;
|
||||
Ok(0)
|
||||
}
|
||||
},
|
||||
// return u32::max_value() if no value exists for the key.
|
||||
ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => {
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| DummyUserError)?;
|
||||
let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?;
|
||||
let maybe_value = this.ext.storage(&key);
|
||||
if let Some(preimage) = this.hash_lookup.get(&key) {
|
||||
trace!(target: "wasm-trace", " Getting storage: %{} == {} [k={}]", ascii_format(&preimage), if let Some(ref b) = maybe_value { format!("{}", HexDisplay::from(b)) } else { "<empty>".to_owned() }, HexDisplay::from(&key));
|
||||
@@ -263,7 +265,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
if let Some(value) = maybe_value {
|
||||
let value = &value[value_offset as usize..];
|
||||
let written = ::std::cmp::min(value_len as usize, value.len());
|
||||
this.memory.set(value_data, &value[..written]).map_err(|_| DummyUserError)?;
|
||||
this.memory.set(value_data, &value[..written]).map_err(|_| UserError("Invalid attempt to set value in ext_get_storage_into"))?;
|
||||
Ok(written as u32)
|
||||
} else {
|
||||
Ok(u32::max_value())
|
||||
@@ -271,22 +273,22 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
},
|
||||
ext_storage_root(result: *mut u8) => {
|
||||
let r = this.ext.storage_root();
|
||||
this.memory.set(result, &r[..]).map_err(|_| DummyUserError)?;
|
||||
this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => {
|
||||
let values = (0..lens_len)
|
||||
.map(|i| this.memory.read_primitive(lens_data + i * 4))
|
||||
.collect::<::std::result::Result<Vec<u32>, DummyUserError>>()?
|
||||
.collect::<::std::result::Result<Vec<u32>, UserError>>()?
|
||||
.into_iter()
|
||||
.scan(0u32, |acc, v| { let o = *acc; *acc += v; Some((o, v)) })
|
||||
.map(|(offset, len)|
|
||||
this.memory.get(values_data + offset, len as usize)
|
||||
.map_err(|_| DummyUserError)
|
||||
.map_err(|_| UserError("Invalid attempt to get memory in ext_enumerated_trie_root"))
|
||||
)
|
||||
.collect::<::std::result::Result<Vec<_>, DummyUserError>>()?;
|
||||
.collect::<::std::result::Result<Vec<_>, UserError>>()?;
|
||||
let r = ordered_trie_root(values.into_iter());
|
||||
this.memory.set(result, &r[..]).map_err(|_| DummyUserError)?;
|
||||
this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_enumerated_trie_root"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_chain_id() -> u64 => {
|
||||
@@ -299,7 +301,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
this.hash_lookup.insert(hashed.to_vec(), vec![]);
|
||||
hashed
|
||||
} else {
|
||||
let key = this.memory.get(data, len as usize).map_err(|_| DummyUserError)?;
|
||||
let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?;
|
||||
let hashed_key = twox_128(&key);
|
||||
if let Ok(skey) = ::std::str::from_utf8(&key) {
|
||||
trace!(target: "xxhash", "XXhash: {} -> {}", skey, HexDisplay::from(&hashed_key));
|
||||
@@ -310,33 +312,33 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
hashed_key
|
||||
};
|
||||
|
||||
this.memory.set(out, &result).map_err(|_| DummyUserError)?;
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_128"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_twox_256(data: *const u8, len: u32, out: *mut u8) => {
|
||||
let result = if len == 0 {
|
||||
twox_256(&[0u8; 0])
|
||||
} else {
|
||||
twox_256(&this.memory.get(data, len as usize).map_err(|_| DummyUserError)?)
|
||||
twox_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?)
|
||||
};
|
||||
this.memory.set(out, &result).map_err(|_| DummyUserError)?;
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_256"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => {
|
||||
let result = if len == 0 {
|
||||
blake2_256(&[0u8; 0])
|
||||
} else {
|
||||
blake2_256(&this.memory.get(data, len as usize).map_err(|_| DummyUserError)?)
|
||||
blake2_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?)
|
||||
};
|
||||
this.memory.set(out, &result).map_err(|_| DummyUserError)?;
|
||||
this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?;
|
||||
Ok(())
|
||||
},
|
||||
ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => {
|
||||
let mut sig = [0u8; 64];
|
||||
this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| DummyUserError)?;
|
||||
this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?;
|
||||
let mut pubkey = [0u8; 32];
|
||||
this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| DummyUserError)?;
|
||||
let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| DummyUserError)?;
|
||||
this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?;
|
||||
let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?;
|
||||
|
||||
Ok(if ::ed25519::verify(&sig, &msg, &pubkey) {
|
||||
0
|
||||
@@ -345,15 +347,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
})
|
||||
},
|
||||
ext_sandbox_instantiate(dispatch_thunk_idx: usize, wasm_ptr: *const u8, wasm_len: usize, imports_ptr: *const u8, imports_len: usize, state: usize) -> u32 => {
|
||||
let wasm = this.memory.get(wasm_ptr, wasm_len as usize).map_err(|_| DummyUserError)?;
|
||||
let raw_env_def = this.memory.get(imports_ptr, imports_len as usize).map_err(|_| DummyUserError)?;
|
||||
let wasm = this.memory.get(wasm_ptr, wasm_len as usize).map_err(|_| UserError("Sandbox error"))?;
|
||||
let raw_env_def = this.memory.get(imports_ptr, imports_len as usize).map_err(|_| UserError("Sandbox error"))?;
|
||||
|
||||
// Extract a dispatch thunk from instance's table by the specified index.
|
||||
let dispatch_thunk = {
|
||||
let table = this.table.as_ref().ok_or_else(|| DummyUserError)?;
|
||||
let table = this.table.as_ref().ok_or_else(|| UserError("Sandbox error"))?;
|
||||
table.get(dispatch_thunk_idx)
|
||||
.map_err(|_| DummyUserError)?
|
||||
.ok_or_else(|| DummyUserError)?
|
||||
.map_err(|_| UserError("Sandbox error"))?
|
||||
.ok_or_else(|| UserError("Sandbox error"))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
@@ -368,10 +370,10 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, state: usize) -> u32 => {
|
||||
trace!(target: "runtime-sandbox", "invoke, instance_idx={}", instance_idx);
|
||||
let export = this.memory.get(export_ptr, export_len as usize)
|
||||
.map_err(|_| DummyUserError)
|
||||
.map_err(|_| UserError("Sandbox error"))
|
||||
.and_then(|b|
|
||||
String::from_utf8(b)
|
||||
.map_err(|_| DummyUserError)
|
||||
.map_err(|_| UserError("Sandbox error"))
|
||||
)?;
|
||||
|
||||
let instance = this.sandbox_store.instance(instance_idx)?;
|
||||
@@ -388,17 +390,17 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
|
||||
trace!(target: "runtime-sandbox", "invoke, instance_idx={}", instance_idx);
|
||||
let export = this.memory.get(export_ptr, export_len as usize)
|
||||
.map_err(|_| DummyUserError)
|
||||
.map_err(|_| UserError("Sandbox error"))
|
||||
.and_then(|b|
|
||||
String::from_utf8(b)
|
||||
.map_err(|_| DummyUserError)
|
||||
.map_err(|_| UserError("Sandbox error"))
|
||||
)?;
|
||||
|
||||
// Deserialize arguments and convert them into wasmi types.
|
||||
let serialized_args = this.memory.get(args_ptr, args_len as usize)
|
||||
.map_err(|_| DummyUserError)?;
|
||||
.map_err(|_| UserError("Sandbox error"))?;
|
||||
let args = Vec::<sandbox_primitives::TypedValue>::decode(&mut &serialized_args[..])
|
||||
.ok_or_else(|| DummyUserError)?
|
||||
.ok_or_else(|| UserError("Sandbox error"))?
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
@@ -412,11 +414,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
// Serialize return value and write it back into the memory.
|
||||
sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| {
|
||||
if val.len() > return_val_len as usize {
|
||||
Err(DummyUserError)?;
|
||||
Err(UserError("Sandbox error"))?;
|
||||
}
|
||||
this.memory
|
||||
.set(return_val_ptr, val)
|
||||
.map_err(|_| DummyUserError)?;
|
||||
.map_err(|_| UserError("Sandbox error"))?;
|
||||
Ok(sandbox_primitives::ERR_OK)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ use wasmi::nan_preserving_float::{F32, F64};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DummyUserError;
|
||||
impl fmt::Display for DummyUserError {
|
||||
pub struct UserError(pub &'static str);
|
||||
impl fmt::Display for UserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "DummyUserError")
|
||||
write!(f, "UserError: {}", self.0)
|
||||
}
|
||||
}
|
||||
impl HostError for DummyUserError {
|
||||
impl HostError for UserError {
|
||||
}
|
||||
|
||||
pub trait ConvertibleToWasm { const VALUE_TYPE: ValueType; type NativeType; fn to_runtime_value(self) -> RuntimeValue; }
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user