mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 14:27:57 +00:00
Fix error handling in sandboxing/contracts modules (#744)
* Fix error handling in sandboxing/contracts modules * Add some docs. * Add some tests. * grammar
This commit is contained in:
committed by
Gav Wood
parent
400a22ebe5
commit
488830e81a
@@ -335,11 +335,27 @@ impl SandboxInstance {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error occured during instantiation of a sandboxed module.
|
||||
pub enum InstantiationError {
|
||||
/// Something wrong with the environment definition. It either can't
|
||||
/// be decoded, have a reference to a non-existent or torn down memory instance.
|
||||
EnvironmentDefintionCorrupted,
|
||||
/// Provided module isn't recognized as a valid webassembly binary.
|
||||
ModuleDecoding,
|
||||
/// Module is a well-formed webassembly binary but could not be instantiated. This could
|
||||
/// happen because, e.g. the module imports entries not provided by the environment.
|
||||
Instantiation,
|
||||
/// Module is well-formed, instantiated and linked, but while executing the start function
|
||||
/// a trap was generated.
|
||||
StartTrapped,
|
||||
}
|
||||
|
||||
fn decode_environment_definition(
|
||||
raw_env_def: &[u8],
|
||||
memories: &[Option<MemoryRef>],
|
||||
) -> Result<(Imports, GuestToSupervisorFunctionMapping), UserError> {
|
||||
let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]).ok_or_else(|| UserError("Sandbox error"))?;
|
||||
) -> Result<(Imports, GuestToSupervisorFunctionMapping), InstantiationError> {
|
||||
let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..])
|
||||
.ok_or_else(|| InstantiationError::EnvironmentDefintionCorrupted)?;
|
||||
|
||||
let mut func_map = HashMap::new();
|
||||
let mut memories_map = HashMap::new();
|
||||
@@ -359,8 +375,8 @@ fn decode_environment_definition(
|
||||
let memory_ref = memories
|
||||
.get(memory_idx as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| UserError("Sandbox error"))?
|
||||
.ok_or_else(|| UserError("Sandbox error"))?;
|
||||
.ok_or_else(|| InstantiationError::EnvironmentDefintionCorrupted)?
|
||||
.ok_or_else(|| InstantiationError::EnvironmentDefintionCorrupted)?;
|
||||
memories_map.insert((module, field), memory_ref);
|
||||
}
|
||||
}
|
||||
@@ -395,12 +411,12 @@ pub fn instantiate<FE: SandboxCapabilities + Externals>(
|
||||
wasm: &[u8],
|
||||
raw_env_def: &[u8],
|
||||
state: u32,
|
||||
) -> Result<u32, UserError> {
|
||||
) -> Result<u32, InstantiationError> {
|
||||
let (imports, guest_to_supervisor_mapping) =
|
||||
decode_environment_definition(raw_env_def, &supervisor_externals.store().memories)?;
|
||||
|
||||
let module = Module::from_buffer(wasm).map_err(|_| UserError("Sandbox error"))?;
|
||||
let instance = ModuleInstance::new(&module, &imports).map_err(|_| UserError("Sandbox error"))?;
|
||||
let module = Module::from_buffer(wasm).map_err(|_| InstantiationError::ModuleDecoding)?;
|
||||
let instance = ModuleInstance::new(&module, &imports).map_err(|_| InstantiationError::Instantiation)?;
|
||||
|
||||
let sandbox_instance = Rc::new(SandboxInstance {
|
||||
// In general, it's not a very good idea to use `.not_started_instance()` for anything
|
||||
@@ -418,14 +434,14 @@ pub fn instantiate<FE: SandboxCapabilities + Externals>(
|
||||
|guest_externals| {
|
||||
instance
|
||||
.run_start(guest_externals)
|
||||
.map_err(|_| UserError("Sandbox error"))
|
||||
.map_err(|_| InstantiationError::StartTrapped)
|
||||
},
|
||||
)?;
|
||||
|
||||
// At last, register the instance.
|
||||
let instance_idx = supervisor_externals
|
||||
.store_mut()
|
||||
.register_sandbox_instance(sandbox_instance);
|
||||
|
||||
Ok(instance_idx)
|
||||
}
|
||||
|
||||
@@ -674,4 +690,85 @@ mod tests {
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unlinkable_module() {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
let code = wabt::wat2wasm(r#"
|
||||
(module
|
||||
(import "env" "non-existent" (func))
|
||||
|
||||
(func (export "call")
|
||||
)
|
||||
)
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn corrupted_module() {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
// Corrupted wasm file
|
||||
let code = &[0, 0, 0, 0, 1, 0, 0, 0];
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", code).unwrap(),
|
||||
vec![1],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn start_fn_ok() {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
let code = wabt::wat2wasm(r#"
|
||||
(module
|
||||
(func (export "call")
|
||||
)
|
||||
|
||||
(func $start
|
||||
)
|
||||
|
||||
(start $start)
|
||||
)
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(),
|
||||
vec![0],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn start_fn_traps() {
|
||||
let mut ext = TestExternalities::default();
|
||||
let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm");
|
||||
|
||||
let code = wabt::wat2wasm(r#"
|
||||
(module
|
||||
(func (export "call")
|
||||
)
|
||||
|
||||
(func $start
|
||||
unreachable
|
||||
)
|
||||
|
||||
(start $start)
|
||||
)
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(),
|
||||
vec![2],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +344,14 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
5
|
||||
})
|
||||
},
|
||||
ext_sandbox_instantiate(dispatch_thunk_idx: usize, wasm_ptr: *const u8, wasm_len: usize, imports_ptr: *const u8, imports_len: usize, state: usize) -> u32 => {
|
||||
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(|_| UserError("Sandbox error"))?;
|
||||
let raw_env_def = this.memory.get(imports_ptr, imports_len as usize).map_err(|_| UserError("Sandbox error"))?;
|
||||
|
||||
@@ -357,9 +364,14 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
.clone()
|
||||
};
|
||||
|
||||
let instance_idx = sandbox::instantiate(this, dispatch_thunk, &wasm, &raw_env_def, state)?;
|
||||
let instance_idx_or_err_code =
|
||||
match sandbox::instantiate(this, dispatch_thunk, &wasm, &raw_env_def, state) {
|
||||
Ok(instance_idx) => instance_idx,
|
||||
Err(sandbox::InstantiationError::StartTrapped) => sandbox_primitives::ERR_EXECUTION,
|
||||
Err(_) => sandbox_primitives::ERR_MODULE,
|
||||
};
|
||||
|
||||
Ok(instance_idx as u32)
|
||||
Ok(instance_idx_or_err_code as u32)
|
||||
},
|
||||
ext_sandbox_instance_teardown(instance_idx: u32) => {
|
||||
this.sandbox_store.instance_teardown(instance_idx)?;
|
||||
|
||||
Reference in New Issue
Block a user