diff --git a/Cargo.lock b/Cargo.lock index f1219a73d18..cc7801f0653 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1560,6 +1560,11 @@ dependencies = [ "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memory_units" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memorydb" version = "0.1.1" @@ -2298,7 +2303,7 @@ dependencies = [ [[package]] name = "parity-wasm" -version = "0.23.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3487,7 +3492,7 @@ dependencies = [ "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", "wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)", "wasmi 0.0.0 (git+https://github.com/pepyakin/wasmi)", @@ -3496,7 +3501,7 @@ dependencies = [ [[package]] name = "wasm-utils" version = "0.1.0" -source = "git+https://github.com/paritytech/wasm-utils#6fdc1c4ed47a6acb0a4774da505a416dd637bc6d" +source = "git+https://github.com/paritytech/wasm-utils#492761a00573c25b37e09cbc81909e0280fe332f" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3504,16 +3509,17 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi" version = "0.0.0" -source = "git+https://github.com/pepyakin/wasmi#551c99273042deaad869c17798060e2212deacab" +source = "git+https://github.com/pepyakin/wasmi#6b6961bcb62fd837ed2950ea15e274ff87f1c0cf" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3715,6 +3721,7 @@ dependencies = [ "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" +"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e3d709ffbb330e1566dc2f2a3c9b58a5ad4a381f740b810cd305dc3f089bc160" "checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae" @@ -3751,7 +3758,7 @@ dependencies = [ "checksum parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=1a58bf4836c84e1632e27ef607b5a388abd2bf2d)" = "" "checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4c067dfa1a17fe71ab2ca26b18c52dcbd0f4fc04)" = "" "checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=3fb77b61a7f30d6658f81d687e7e415657bd20bd)" = "" -"checksum parity-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ba4b1d4236b76694f6ab8d8d00cdbe1e37c6dd1b5c803d26721f27e097d4d9" +"checksum parity-wasm 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac0d6c23cedb2b51dc3d7b5861eba9eb5826dfa6260daa994ffd5c6c2035182" "checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693" "checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" "checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595" diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index d3f2852c64a..0099d2a5188 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Parity Technologies "] byteorder = "1.0" ethereum-types = "0.2" log = "0.3" -parity-wasm = "0.23" +parity-wasm = "0.27" libc = "0.2" wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } vm = { path = "../vm" } diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index c5b30df842a..7ffaaf98abd 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -19,7 +19,7 @@ use std::cell::RefCell; use wasmi::{ self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor, - MemoryRef, MemoryInstance, + MemoryRef, MemoryInstance, memory_units, }; /// Internal ids all functions runtime supports. This is just a glue for wasmi interpreter @@ -219,7 +219,10 @@ impl ImportResolver { let mut mem_ref = self.memory.borrow_mut(); if mem_ref.is_none() { *mem_ref = Some( - MemoryInstance::alloc(0, Some(0)).expect("Memory allocation (0, 0) should not fail; qed") + MemoryInstance::alloc( + memory_units::Pages(0), + Some(memory_units::Pages(0)), + ).expect("Memory allocation (0, 0) should not fail; qed") ); } } @@ -229,7 +232,7 @@ impl ImportResolver { /// Returns memory size module initially requested pub fn memory_size(&self) -> Result { - Ok(self.memory_ref().size()) + Ok(self.memory_ref().current_size().0 as u32) } } @@ -281,7 +284,10 @@ impl wasmi::ModuleImportResolver for ImportResolver { { Err(Error::Instantiation("Module requested too much memory".to_owned())) } else { - let mem = MemoryInstance::alloc(descriptor.initial(), descriptor.maximum())?; + let mem = MemoryInstance::alloc( + memory_units::Pages(descriptor.initial() as usize), + descriptor.maximum().map(|x| memory_units::Pages(x as usize)), + )?; *self.memory.borrow_mut() = Some(mem.clone()); Ok(mem) } diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index 322a5913245..e07d3eee9a2 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -34,7 +34,7 @@ mod panic_payload; mod parser; use vm::{GasLeft, ReturnData, ActionParams}; -use wasmi::Error as InterpreterError; +use wasmi::{Error as InterpreterError, Trap}; use runtime::{Runtime, RuntimeContext}; @@ -42,17 +42,23 @@ use ethereum_types::U256; /// Wrapped interpreter error #[derive(Debug)] -pub struct Error(InterpreterError); +pub enum Error { + Interpreter(InterpreterError), + Trap(Trap), +} impl From for Error { fn from(e: InterpreterError) -> Self { - Error(e) + Error::Interpreter(e) } } impl From for vm::Error { fn from(e: Error) -> Self { - vm::Error::Wasm(format!("Wasm runtime error: {:?}", e.0)) + match e { + Error::Interpreter(e) => vm::Error::Wasm(format!("Wasm runtime error: {:?}", e)), + Error::Trap(e) => vm::Error::Wasm(format!("Wasm contract trap: {:?}", e)), + } } } @@ -70,14 +76,14 @@ impl vm::Vm for WasmInterpreter { fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result { let (module, data) = parser::payload(¶ms, ext.schedule().wasm())?; - let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error)?; + let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?; let instantiation_resolover = env::ImportResolver::with_limit(16); let module_instance = wasmi::ModuleInstance::new( &loaded_module, &wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolover) - ).map_err(Error)?; + ).map_err(Error::Interpreter)?; let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) / U256::from(ext.schedule().wasm().opcodes_mul); @@ -87,7 +93,7 @@ impl vm::Vm for WasmInterpreter { return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas (wasm adjusted) >= 2^64".to_owned())); } - let initial_memory = instantiation_resolover.memory_size().map_err(Error)?; + let initial_memory = instantiation_resolover.memory_size().map_err(Error::Interpreter)?; trace!(target: "wasm", "Contract requested {:?} pages of initial memory", initial_memory); let (gas_left, result) = { @@ -114,7 +120,7 @@ impl vm::Vm for WasmInterpreter { assert!(runtime.schedule().wasm().initial_mem < 1 << 16); runtime.charge(|s| initial_memory as u64 * s.wasm().initial_mem as u64)?; - let module_instance = module_instance.run_start(&mut runtime).map_err(Error)?; + let module_instance = module_instance.run_start(&mut runtime).map_err(Error::Trap)?; match module_instance.invoke_export("call", &[], &mut runtime) { Ok(_) => { }, diff --git a/ethcore/wasm/src/parser.rs b/ethcore/wasm/src/parser.rs index 8ba7a7098d1..d76b5d038fa 100644 --- a/ethcore/wasm/src/parser.rs +++ b/ethcore/wasm/src/parser.rs @@ -22,14 +22,18 @@ use parity_wasm::elements::{self, Deserialize}; use parity_wasm::peek_size; fn gas_rules(wasm_costs: &vm::WasmCosts) -> rules::Set { - rules::Set::new({ - let mut vals = ::std::collections::HashMap::with_capacity(4); - vals.insert(rules::InstructionType::Load, wasm_costs.mem as u32); - vals.insert(rules::InstructionType::Store, wasm_costs.mem as u32); - vals.insert(rules::InstructionType::Div, wasm_costs.div as u32); - vals.insert(rules::InstructionType::Mul, wasm_costs.mul as u32); - vals - }).with_grow_cost(wasm_costs.grow_mem) + rules::Set::new( + 1, + { + let mut vals = ::std::collections::HashMap::with_capacity(8); + vals.insert(rules::InstructionType::Load, rules::Metering::Fixed(wasm_costs.mem as u32)); + vals.insert(rules::InstructionType::Store, rules::Metering::Fixed(wasm_costs.mem as u32)); + vals.insert(rules::InstructionType::Div, rules::Metering::Fixed(wasm_costs.div as u32)); + vals.insert(rules::InstructionType::Mul, rules::Metering::Fixed(wasm_costs.mul as u32)); + vals + }) + .with_grow_cost(wasm_costs.grow_mem) + .with_forbidden_floats() } /// Splits payload to code and data according to params.params_type, also @@ -71,7 +75,9 @@ pub fn payload<'a>(params: &'a vm::ActionParams, wasm_costs: &vm::WasmCosts) let contract_module = wasm_utils::inject_gas_counter( deserialized_module, &gas_rules(wasm_costs), - ); + ).map_err(|_| vm::Error::Wasm(format!("Wasm contract error: bytecode invalid")))?; + + ::parity_wasm::elements::serialize_to_file("./debug.wasm", contract_module.clone()); let data = match params.params_type { vm::ParamsType::Embedded => { diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index adac1208908..01cb521002d 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -1,6 +1,6 @@ use ethereum_types::{U256, H256, Address}; use vm::{self, CallType}; -use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError}; +use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap}; use super::panic_payload; pub struct RuntimeContext { @@ -58,9 +58,15 @@ pub enum Error { impl wasmi::HostError for Error { } +impl From for Error { + fn from(trap: Trap) -> Self { + Error::Other + } +} + impl From for Error { - fn from(interpreter_err: InterpreterError) -> Self { - match interpreter_err { + fn from(err: InterpreterError) -> Self { + match err { InterpreterError::Value(_) => Error::InvalidSyscall, InterpreterError::Memory(_) => Error::MemoryAccessViolation, _ => Error::Other, @@ -203,8 +209,8 @@ impl<'a> Runtime<'a> { /// Read from the storage to wasm memory pub fn storage_read(&mut self, args: RuntimeArgs) -> Result<()> { - let key = self.h256_at(args.nth(0)?)?; - let val_ptr: u32 = args.nth(1)?; + let key = self.h256_at(args.nth_checked(0)?)?; + let val_ptr: u32 = args.nth_checked(1)?; let val = self.ext.storage_at(&key).map_err(|_| Error::StorageReadError)?; @@ -218,8 +224,8 @@ impl<'a> Runtime<'a> { /// Write to storage from wasm memory pub fn storage_write(&mut self, args: RuntimeArgs) -> Result<()> { - let key = self.h256_at(args.nth(0)?)?; - let val_ptr: u32 = args.nth(1)?; + let key = self.h256_at(args.nth_checked(0)?)?; + let val_ptr: u32 = args.nth_checked(1)?; let val = self.h256_at(val_ptr)?; let former_val = self.ext.storage_at(&key).map_err(|_| Error::StorageUpdateError)?; @@ -250,8 +256,8 @@ impl<'a> Runtime<'a> { /// * pointer in sandboxed memory where result is /// * the length of the result pub fn ret(&mut self, args: RuntimeArgs) -> Result<()> { - let ptr: u32 = args.nth(0)?; - let len: u32 = args.nth(1)?; + let ptr: u32 = args.nth_checked(0)?; + let len: u32 = args.nth_checked(1)?; trace!(target: "wasm", "Contract ret: {} bytes @ {}", len, ptr); @@ -273,7 +279,7 @@ impl<'a> Runtime<'a> { /// Report gas cost with the params passed in wasm stack fn gas(&mut self, args: RuntimeArgs) -> Result<()> { - let amount: u32 = args.nth(0)?; + let amount: u32 = args.nth_checked(0)?; if self.charge_gas(amount as u64) { Ok(()) } else { @@ -288,7 +294,7 @@ impl<'a> Runtime<'a> { /// Write input bytes to the memory location using the passed pointer fn fetch_input(&mut self, args: RuntimeArgs) -> Result<()> { - let ptr: u32 = args.nth(0)?; + let ptr: u32 = args.nth_checked(0)?; self.memory.set(ptr, &self.args[..])?; Ok(()) } @@ -298,8 +304,8 @@ impl<'a> Runtime<'a> { /// Contract can invoke this when he encounters unrecoverable error. fn panic(&mut self, args: RuntimeArgs) -> Result<()> { - let payload_ptr: u32 = args.nth(0)?; - let payload_len: u32 = args.nth(1)?; + let payload_ptr: u32 = args.nth_checked(0)?; + let payload_len: u32 = args.nth_checked(1)?; let raw_payload = self.memory.get(payload_ptr, payload_len as usize)?; let payload = panic_payload::decode(&raw_payload); @@ -333,26 +339,26 @@ impl<'a> Runtime<'a> { { trace!(target: "wasm", "runtime: CALL({:?})", call_type); - let gas: u64 = args.nth(0)?; + let gas: u64 = args.nth_checked(0)?; trace!(target: "wasm", " gas: {:?}", gas); - let address = self.address_at(args.nth(1)?)?; + let address = self.address_at(args.nth_checked(1)?)?; trace!(target: "wasm", " address: {:?}", address); let vofs = if use_val { 1 } else { 0 }; - let val = if use_val { Some(self.u256_at(args.nth(2)?)?) } else { None }; + let val = if use_val { Some(self.u256_at(args.nth_checked(2)?)?) } else { None }; trace!(target: "wasm", " val: {:?}", val); - let input_ptr: u32 = args.nth(2 + vofs)?; + let input_ptr: u32 = args.nth_checked(2 + vofs)?; trace!(target: "wasm", " input_ptr: {:?}", input_ptr); - let input_len: u32 = args.nth(3 + vofs)?; + let input_len: u32 = args.nth_checked(3 + vofs)?; trace!(target: "wasm", " input_len: {:?}", input_len); - let result_ptr: u32 = args.nth(4 + vofs)?; + let result_ptr: u32 = args.nth_checked(4 + vofs)?; trace!(target: "wasm", " result_ptr: {:?}", result_ptr); - let result_alloc_len: u32 = args.nth(5 + vofs)?; + let result_alloc_len: u32 = args.nth_checked(5 + vofs)?; trace!(target: "wasm", " result_len: {:?}", result_alloc_len); if let Some(ref val) = val { @@ -453,7 +459,7 @@ impl<'a> Runtime<'a> { /// Returns value (in Wei) passed to contract pub fn value(&mut self, args: RuntimeArgs) -> Result<()> { let val = self.context.value; - self.return_u256_ptr(args.nth(0)?, val) + self.return_u256_ptr(args.nth_checked(0)?, val) } /// Creates a new contract @@ -470,13 +476,13 @@ impl<'a> Runtime<'a> { // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; // trace!(target: "wasm", "runtime: CREATE"); - let endowment = self.u256_at(args.nth(0)?)?; + let endowment = self.u256_at(args.nth_checked(0)?)?; trace!(target: "wasm", " val: {:?}", endowment); - let code_ptr: u32 = args.nth(1)?; + let code_ptr: u32 = args.nth_checked(1)?; trace!(target: "wasm", " code_ptr: {:?}", code_ptr); - let code_len: u32 = args.nth(2)?; + let code_len: u32 = args.nth_checked(2)?; trace!(target: "wasm", " code_len: {:?}", code_len); - let result_ptr: u32 = args.nth(3)?; + let result_ptr: u32 = args.nth_checked(3)?; trace!(target: "wasm", "result_ptr: {:?}", result_ptr); let code = self.memory.get(code_ptr, code_len as usize)?; @@ -518,8 +524,8 @@ impl<'a> Runtime<'a> { fn debug(&mut self, args: RuntimeArgs) -> Result<()> { - let msg_ptr: u32 = args.nth(0)?; - let msg_len: u32 = args.nth(1)?; + let msg_ptr: u32 = args.nth_checked(0)?; + let msg_len: u32 = args.nth_checked(1)?; let msg = String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?) .map_err(|_| Error::BadUtf8)?; @@ -532,7 +538,7 @@ impl<'a> Runtime<'a> { /// Pass suicide to state runtime pub fn suicide(&mut self, args: RuntimeArgs) -> Result<()> { - let refund_address = self.address_at(args.nth(0)?)?; + let refund_address = self.address_at(args.nth_checked(0)?)?; if self.ext.exists(&refund_address).map_err(|_| Error::SuicideAbort)? { trace!(target: "wasm", "Suicide: refund to existing address {}", refund_address); @@ -551,8 +557,8 @@ impl<'a> Runtime<'a> { /// Signature: `fn blockhash(number: i64, dest: *mut u8)` pub fn blockhash(&mut self, args: RuntimeArgs) -> Result<()> { self.adjusted_charge(|schedule| schedule.blockhash_gas as u64)?; - let hash = self.ext.blockhash(&U256::from(args.nth::(0)?)); - self.memory.set(args.nth(1)?, &*hash)?; + let hash = self.ext.blockhash(&U256::from(args.nth_checked::(0)?)); + self.memory.set(args.nth_checked(1)?, &*hash)?; Ok(()) } @@ -565,37 +571,37 @@ impl<'a> Runtime<'a> { /// Signature: `fn coinbase(dest: *mut u8)` pub fn coinbase(&mut self, args: RuntimeArgs) -> Result<()> { let coinbase = self.ext.env_info().author; - self.return_address_ptr(args.nth(0)?, coinbase) + self.return_address_ptr(args.nth_checked(0)?, coinbase) } /// Signature: `fn difficulty(dest: *mut u8)` pub fn difficulty(&mut self, args: RuntimeArgs) -> Result<()> { let difficulty = self.ext.env_info().difficulty; - self.return_u256_ptr(args.nth(0)?, difficulty) + self.return_u256_ptr(args.nth_checked(0)?, difficulty) } /// Signature: `fn gaslimit(dest: *mut u8)` pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> { let gas_limit = self.ext.env_info().gas_limit; - self.return_u256_ptr(args.nth(0)?, gas_limit) + self.return_u256_ptr(args.nth_checked(0)?, gas_limit) } /// Signature: `fn address(dest: *mut u8)` pub fn address(&mut self, args: RuntimeArgs) -> Result<()> { let address = self.context.address; - self.return_address_ptr(args.nth(0)?, address) + self.return_address_ptr(args.nth_checked(0)?, address) } /// Signature: `sender(dest: *mut u8)` pub fn sender(&mut self, args: RuntimeArgs) -> Result<()> { let sender = self.context.sender; - self.return_address_ptr(args.nth(0)?, sender) + self.return_address_ptr(args.nth_checked(0)?, sender) } /// Signature: `origin(dest: *mut u8)` pub fn origin(&mut self, args: RuntimeArgs) -> Result<()> { let origin = self.context.origin; - self.return_address_ptr(args.nth(0)?, origin) + self.return_address_ptr(args.nth_checked(0)?, origin) } /// Signature: `timestamp() -> i64` @@ -607,10 +613,10 @@ impl<'a> Runtime<'a> { /// Signature: `fn elog(topic_ptr: *const u8, topic_count: u32, data_ptr: *const u8, data_len: u32)` pub fn elog(&mut self, args: RuntimeArgs) -> Result<()> { - let topic_ptr: u32 = args.nth(0)?; - let topic_count: u32 = args.nth(1)?; - let data_ptr: u32 = args.nth(2)?; - let data_len: u32 = args.nth(3)?; + let topic_ptr: u32 = args.nth_checked(0)?; + let topic_count: u32 = args.nth_checked(1)?; + let data_ptr: u32 = args.nth_checked(2)?; + let data_len: u32 = args.nth_checked(3)?; if topic_count > 4 { return Err(Error::Log.into()); @@ -643,7 +649,7 @@ impl<'a> Runtime<'a> { mod ext_impl { - use wasmi::{Externals, RuntimeArgs, RuntimeValue, Error}; + use wasmi::{Externals, RuntimeArgs, RuntimeValue, Error, Trap}; use env::ids::*; macro_rules! void { @@ -663,7 +669,7 @@ mod ext_impl { &mut self, index: usize, args: RuntimeArgs, - ) -> Result, Error> { + ) -> Result, Trap> { match index { STORAGE_WRITE_FUNC => void!(self.storage_write(args)), STORAGE_READ_FUNC => void!(self.storage_read(args)),