mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 20:01:08 +00:00
Fix sandbox::Memory lifecycle + sandox get memory function for no_std env (#845)
* Fix `sandbox::Memory` lifecycle for no_std env * Retain memories in env_def builder and instance * Add scoped memory creation to test RC semantics * Add deploying_wasm_contract_should_work test. * Fix sandboxed memory set function.
This commit is contained in:
committed by
Gav Wood
parent
a5a7dd2480
commit
2414ffdac0
@@ -438,11 +438,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
ext_sandbox_memory_set(memory_idx: u32, offset: u32, val_ptr: *const u8, val_len: usize) -> u32 => {
|
||||
let dst_memory = this.sandbox_store.memory(memory_idx)?;
|
||||
|
||||
let data = match this.memory.get(offset, val_len as usize) {
|
||||
let data = match this.memory.get(val_ptr, val_len as usize) {
|
||||
Ok(data) => data,
|
||||
Err(_) => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS),
|
||||
};
|
||||
match dst_memory.set(val_ptr, &data) {
|
||||
match dst_memory.set(offset, &data) {
|
||||
Err(_) => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
@@ -120,9 +120,21 @@ fn execute_sandboxed(code: &[u8], args: &[sandbox::TypedValue]) -> Result<sandbo
|
||||
|
||||
let mut state = State { counter: 0 };
|
||||
|
||||
let mut env_builder = sandbox::EnvironmentDefinitionBuilder::new();
|
||||
env_builder.add_host_func("env", "assert", env_assert);
|
||||
env_builder.add_host_func("env", "inc_counter", env_inc_counter);
|
||||
let env_builder = {
|
||||
let mut env_builder = sandbox::EnvironmentDefinitionBuilder::new();
|
||||
env_builder.add_host_func("env", "assert", env_assert);
|
||||
env_builder.add_host_func("env", "inc_counter", env_inc_counter);
|
||||
let memory = match sandbox::Memory::new(1, Some(16)) {
|
||||
Ok(m) => m,
|
||||
Err(_) => unreachable!("
|
||||
Memory::new() can return Err only if parameters are borked; \
|
||||
We passing params here explicitly and they're correct; \
|
||||
Memory::new() can't return a Error qed"
|
||||
),
|
||||
};
|
||||
env_builder.add_memory("env", "memory", memory.clone());
|
||||
env_builder
|
||||
};
|
||||
|
||||
let mut instance = sandbox::Instance::new(code, &env_builder, &mut state)?;
|
||||
let result = instance.invoke(b"call", args, &mut state);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::{slice, marker, mem};
|
||||
use rstd::rc::Rc;
|
||||
use codec::{Decode, Encode};
|
||||
use primitives::sandbox as sandbox_primitives;
|
||||
use super::{Error, TypedValue, ReturnValue, HostFuncType};
|
||||
@@ -89,9 +90,23 @@ mod ffi {
|
||||
}
|
||||
}
|
||||
|
||||
struct MemoryHandle {
|
||||
memory_idx: u32,
|
||||
}
|
||||
|
||||
impl Drop for MemoryHandle {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::ext_sandbox_memory_teardown(self.memory_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Memory {
|
||||
memory_idx: u32,
|
||||
// Handle to memory instance is wrapped to add reference-counting semantics
|
||||
// to `Memory`.
|
||||
handle: Rc<MemoryHandle>,
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
@@ -106,12 +121,14 @@ impl Memory {
|
||||
};
|
||||
match result {
|
||||
sandbox_primitives::ERR_MODULE => Err(Error::Module),
|
||||
memory_idx => Ok(Memory { memory_idx }),
|
||||
memory_idx => Ok(Memory {
|
||||
handle: Rc::new(MemoryHandle { memory_idx, }),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> {
|
||||
let result = unsafe { ffi::ext_sandbox_memory_get(self.memory_idx, offset, buf.as_mut_ptr(), buf.len()) };
|
||||
let result = unsafe { ffi::ext_sandbox_memory_get(self.handle.memory_idx, offset, buf.as_mut_ptr(), buf.len()) };
|
||||
match result {
|
||||
sandbox_primitives::ERR_OK => Ok(()),
|
||||
sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds),
|
||||
@@ -120,7 +137,7 @@ impl Memory {
|
||||
}
|
||||
|
||||
pub fn set(&self, offset: u32, val: &[u8]) -> Result<(), Error> {
|
||||
let result = unsafe { ffi::ext_sandbox_memory_set(self.memory_idx, offset, val.as_ptr(), val.len()) };
|
||||
let result = unsafe { ffi::ext_sandbox_memory_set(self.handle.memory_idx, offset, val.as_ptr(), val.len()) };
|
||||
match result {
|
||||
sandbox_primitives::ERR_OK => Ok(()),
|
||||
sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds),
|
||||
@@ -129,16 +146,9 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Memory {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::ext_sandbox_memory_teardown(self.memory_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EnvironmentDefinitionBuilder<T> {
|
||||
env_def: sandbox_primitives::EnvironmentDefinition,
|
||||
retained_memories: Vec<Memory>,
|
||||
_marker: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -148,6 +158,7 @@ impl<T> EnvironmentDefinitionBuilder<T> {
|
||||
env_def: sandbox_primitives::EnvironmentDefinition {
|
||||
entries: Vec::new(),
|
||||
},
|
||||
retained_memories: Vec::new(),
|
||||
_marker: marker::PhantomData::<T>,
|
||||
}
|
||||
}
|
||||
@@ -183,13 +194,17 @@ impl<T> EnvironmentDefinitionBuilder<T> {
|
||||
N1: Into<Vec<u8>>,
|
||||
N2: Into<Vec<u8>>,
|
||||
{
|
||||
let mem = sandbox_primitives::ExternEntity::Memory(mem.memory_idx as u32);
|
||||
// We need to retain memory to keep it alive while the EnvironmentDefinitionBuilder alive.
|
||||
self.retained_memories.push(mem.clone());
|
||||
|
||||
let mem = sandbox_primitives::ExternEntity::Memory(mem.handle.memory_idx as u32);
|
||||
self.add_entry(module, field, mem);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Instance<T> {
|
||||
instance_idx: u32,
|
||||
_retained_memories: Vec<Memory>,
|
||||
_marker: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -256,8 +271,11 @@ impl<T> Instance<T> {
|
||||
sandbox_primitives::ERR_EXECUTION => return Err(Error::Execution),
|
||||
instance_idx => instance_idx,
|
||||
};
|
||||
// We need to retain memories to keep them alive while the Instance is alive.
|
||||
let retained_memories = env_def_builder.retained_memories.clone();
|
||||
Ok(Instance {
|
||||
instance_idx,
|
||||
_retained_memories: retained_memories,
|
||||
_marker: marker::PhantomData::<T>,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user