diff --git a/Cargo.lock b/Cargo.lock index 461dbd5f4..d568f38bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3514,6 +3514,7 @@ dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-logger 1.9.0", "ethereum-types 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (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.15.3 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index e250bfa1c..53e585d37 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -128,6 +128,8 @@ pub struct WasmCosts { /// Memory (load/store) operations multiplier. pub mem: u32, /// Memory copy operation, per byte. + pub mem_cmp: u32, + /// Memory copy operation, per byte. pub mem_copy: u32, /// Memory move operation, per byte. pub mem_move: u32, @@ -148,6 +150,7 @@ impl Default for WasmCosts { div: 16, mul: 4, mem: 2, + mem_cmp: 1, mem_copy: 1, mem_move: 1, mem_set: 1, diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index 19f6ebc0d..2b790e099 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -8,6 +8,7 @@ byteorder = "1.0" ethereum-types = "0.1" log = "0.3" parity-wasm = "0.15" +libc = "0.2" wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } vm = { path = "../vm" } ethcore-logger = { path = "../../logger" } diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index cae673858..27c7c93a9 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -92,6 +92,11 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[ &[I32; 3], Some(I32), ), + Static( + "_ext_memcmp", + &[I32; 3], + Some(I32), + ), Static( "_ext_memcpy", &[I32; 3], diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index bd56dd298..241004c6a 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -22,6 +22,7 @@ extern crate ethereum_types; extern crate ethcore_logger; extern crate byteorder; extern crate parity_wasm; +extern crate libc; extern crate wasm_utils; mod runtime; diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 7071f9944..5b9689537 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -19,6 +19,7 @@ use std::sync::Arc; use byteorder::{LittleEndian, ByteOrder}; +use libc::{memcmp, c_void}; use vm; use panic_payload; @@ -567,6 +568,28 @@ impl<'a, 'b> Runtime<'a, 'b> { &*self.memory } + fn mem_cmp(&mut self, context: InterpreterCallerContext) + -> Result, InterpreterError> + { + // + // method signature: + // fn memcmp(cx: *const u8, ct: *const u8, n: usize) -> i32; + // + + let len = context.value_stack.pop_as::()? as u32; + let cx = context.value_stack.pop_as::()? as u32; + let ct = context.value_stack.pop_as::()? as u32; + + self.charge(|schedule| schedule.wasm.mem_cmp as u64 * len as u64)?; + + let cx = self.memory.get(cx, len as usize)?; + let ct = self.memory.get(ct, len as usize)?; + let result = unsafe { + memcmp(cx.as_ptr() as *const c_void, ct.as_ptr() as *const c_void, len as usize) + }; + Ok(Some(Into::into(result))) + } + fn mem_copy(&mut self, context: InterpreterCallerContext) -> Result, InterpreterError> { @@ -890,6 +913,9 @@ impl<'a, 'b> interpreter::UserFunctionExecutor for Runtime<'a, 'b> { "_emscripten_memcpy_big" => { self.mem_copy(context) }, + "_ext_memcmp" => { + self.mem_cmp(context) + }, "_ext_memcpy" => { self.mem_copy(context) },