Skip to content

Commit

Permalink
Error processing.
Browse files Browse the repository at this point in the history
  • Loading branch information
olonho committed Jun 16, 2020
1 parent c2e0016 commit e8474df
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 21 deletions.
97 changes: 82 additions & 15 deletions runtime/near-vm-runner/src/wasmtime_runner.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::errors::IntoVMError;
use crate::{imports, prepare};
use near_runtime_fees::RuntimeFeesConfig;
use near_vm_errors::FunctionCallError::LinkError;
use near_vm_errors::FunctionCallError::{LinkError, WasmUnknownError};
use near_vm_errors::{FunctionCallError, MethodResolveError, VMError, VMLogicError};
use near_vm_logic::types::PromiseResult;
use near_vm_logic::{External, MemoryLike, VMConfig, VMContext, VMLogic, VMOutcome};
use std::ffi::c_void;
use std::str;
use wasmtime::ExternType::Func;
use wasmtime::{Engine, Limits, Linker, Memory, MemoryType, Module, Store};

pub struct WasmtimeMemory(Memory);
Expand Down Expand Up @@ -59,28 +60,42 @@ impl MemoryLike for WasmtimeMemory {
}
}

fn trap_to_error(trap: &wasmtime::Trap) -> VMError {
if trap.i32_exit_status() == Some(239) {
match imports::last_wasmtime_error() {
Some(VMLogicError::HostError(h)) => {
VMError::FunctionCallError(FunctionCallError::HostError(h.clone()))
}
Some(VMLogicError::ExternalError(s)) => VMError::ExternalError(s.clone()),
Some(VMLogicError::InconsistentStateError(e)) => {
VMError::InconsistentStateError(e.clone())
}
None => panic!("Error is not properly set"),
}
} else {
// VMError::FunctionCallError(LinkError { msg: format!("{:#?}", trap) })
VMError::FunctionCallError(WasmUnknownError)
}
}

impl IntoVMError for anyhow::Error {
fn into_vm_error(self) -> VMError {
// TODO: incorrect
VMError::FunctionCallError(LinkError { msg: format!("{:#?}", self) })
let cause = self.root_cause();
match cause.downcast_ref::<wasmtime::Trap>() {
Some(trap) => trap_to_error(trap),
None => VMError::FunctionCallError(LinkError { msg: format!("{:#?}", cause) }),
}
}
}

impl IntoVMError for wasmtime::Trap {
fn into_vm_error(self) -> VMError {
if self.i32_exit_status() == Some(239) {
match imports::last_wasmtime_error() {
Some(VMLogicError::HostError(h)) => {
VMError::FunctionCallError(FunctionCallError::HostError(h.clone()))
}
Some(VMLogicError::ExternalError(s)) => VMError::ExternalError(s.clone()),
Some(VMLogicError::InconsistentStateError(e)) => {
VMError::InconsistentStateError(e.clone())
}
None => panic!("Error is not properly set"),
}
trap_to_error(&self)
} else {
VMError::FunctionCallError(LinkError { msg: format!("{:#?}", self) })
// VMError::FunctionCallError(LinkError { msg: format!("{:#?}", self) })
VMError::FunctionCallError(WasmUnknownError)
}
}
}
Expand All @@ -103,7 +118,10 @@ pub fn run_wasmtime<'a>(
wasm_config.limit_config.max_memory_pages,
)
.unwrap();
let prepared_code = prepare::prepare_contract(code, wasm_config).unwrap();
let prepared_code = match prepare::prepare_contract(code, wasm_config) {
Ok(code) => code,
Err(err) => return (None, Some(VMError::from(err))),
};
let module = Module::new(&engine, prepared_code).unwrap();
// Note that we don't clone the actual backing memory, just increase the RC.
let memory_copy = memory.clone();
Expand All @@ -114,8 +132,57 @@ pub fn run_wasmtime<'a>(
// lifetimes of the logic instance and pass raw pointers here.
let raw_logic = &mut logic as *mut _ as *mut c_void;
imports::link_wasmtime(&mut linker, memory_copy, raw_logic);
let func_name = match str::from_utf8(method_name) {
Ok(name) => name,
Err(_) => {
return (
None,
Some(VMError::FunctionCallError(FunctionCallError::MethodResolveError(
MethodResolveError::MethodUTF8Error,
))),
)
}
};
if method_name.is_empty() {
return (
None,
Some(VMError::FunctionCallError(FunctionCallError::MethodResolveError(
MethodResolveError::MethodEmptyName,
))),
);
}
match module.get_export(func_name) {
Some(export) => match export {
Func(func_type) => {
if !func_type.params().is_empty() || !func_type.results().is_empty() {
return (
None,
Some(VMError::FunctionCallError(FunctionCallError::MethodResolveError(
MethodResolveError::MethodInvalidSignature,
))),
);
}
}
_ => {
return (
None,
Some(VMError::FunctionCallError(FunctionCallError::MethodResolveError(
MethodResolveError::MethodNotFound,
))),
)
}
},
None => {
return (
None,
Some(VMError::FunctionCallError(FunctionCallError::MethodResolveError(
MethodResolveError::MethodNotFound,
))),
)
}
}
match linker.instantiate(&module) {
Ok(instance) => match instance.get_func(str::from_utf8(method_name).unwrap()) {
Ok(instance) => match instance.get_func(func_name) {
Some(func) => match func.get0::<()>() {
Ok(run) => match run() {
Ok(_) => (Some(logic.outcome()), None),
Expand Down
17 changes: 11 additions & 6 deletions runtime/near-vm-runner/tests/test_error_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,26 +348,31 @@ fn test_bad_import_2() {

#[test]
fn test_bad_import_3() {
let msg = match VMKind::default() {
VMKind::Wasmer => "link error: Incorrect import type, namespace: env, name: input, expected type: global, found type: function",
VMKind::Wasmtime => "\"incompatible import type for `env::input` specified\\ndesired signature was: Global(GlobalType { content: I32, mutability: Const })\\nsignatures available:\\n\\n * Func(FuncType { params: [I64], results: [] })\\n\"",
}.to_string();
assert_eq!(
make_simple_contract_call(&bad_import_global("env"), b"hello"),
(
Some(vm_outcome_with_gas(0)),
Some(VMError::FunctionCallError(FunctionCallError::LinkError{
msg: "link error: Incorrect import type, namespace: env, name: input, expected type: global, found type: function".to_string()
}))
Some(VMError::FunctionCallError(FunctionCallError::LinkError { msg: msg }))
)
);
}

#[test]
fn test_bad_import_4() {
let msg = match VMKind::default() {
VMKind::Wasmer => "link error: Import not found, namespace: env, name: wtf",
VMKind::Wasmtime => "\"unknown import: `env::wtf` has not been defined\"",
}
.to_string();
assert_eq!(
make_simple_contract_call(&bad_import_func("env"), b"hello"),
(
Some(vm_outcome_with_gas(0)),
Some(VMError::FunctionCallError(FunctionCallError::LinkError {
msg: "link error: Import not found, namespace: env, name: wtf".to_string()
}))
Some(VMError::FunctionCallError(FunctionCallError::LinkError { msg: msg }))
)
);
}
Expand Down

0 comments on commit e8474df

Please sign in to comment.