From b3cf9ccb9dec4351187a90459c3c6104f168b59a Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Thu, 2 Aug 2018 16:04:43 +0800 Subject: [PATCH 1/2] implement extend() and remove one TODO --- src/runner.rs | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/runner.rs b/src/runner.rs index 5a9ec84..3a69350 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,5 +1,6 @@ use std::ops; use std::{u32, usize}; +use std::cmp; use std::fmt; use std::iter::repeat; use parity_wasm::elements::Local; @@ -1109,11 +1110,7 @@ impl FunctionContext { .map(RuntimeValue::default) .collect::>(); - // TODO: Replace with extend. - for local in locals { - value_stack.push(local) - .map_err(|_| TrapKind::StackOverflow)?; - } + value_stack.extend(&locals)?; self.is_initialized = true; Ok(()) @@ -1263,8 +1260,47 @@ impl ValueStack { Ok(()) } + #[inline] + fn extend(&mut self, values: &[RuntimeValue]) -> Result<(), TrapKind> { + let len = cmp::min(values.len(), self.buf.len() - self.sp); + self.buf[self.sp..(self.sp+len)].copy_from_slice(&values[..len]); + self.sp += len; + if len < values.len() { + Err(TrapKind::StackOverflow) + } else { + Ok(()) + } + } + #[inline] fn len(&self) -> usize { self.sp } } + +#[cfg(test)] +mod tests { + use super::ValueStack; + use value::RuntimeValue; + + #[test] + fn test_stack_extend() { + let mut stack = ValueStack::with_limit(5); + let values = vec![RuntimeValue::I32(1), RuntimeValue::I32(2), RuntimeValue::I32(3), + RuntimeValue::I32(4), RuntimeValue::I32(5)]; + + assert!(stack.extend(&values).is_ok()); + assert_eq!(stack.len(), 5); + + assert!(stack.push(RuntimeValue::I32(6)).is_err()); + + // check each elements + assert_eq!(stack.pop(), RuntimeValue::I32(5)); + assert_eq!(stack.pop(), RuntimeValue::I32(4)); + assert_eq!(stack.pop(), RuntimeValue::I32(3)); + assert_eq!(stack.pop(), RuntimeValue::I32(2)); + assert_eq!(stack.pop(), RuntimeValue::I32(1)); + + assert_eq!(stack.len(), 0); + } +} From 039c75589ca4030896a973a13acbc383148f8aed Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Tue, 18 Sep 2018 23:32:35 +0800 Subject: [PATCH 2/2] fix according to the comments --- src/runner.rs | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/src/runner.rs b/src/runner.rs index 3a69350..2d7c53a 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,6 +1,5 @@ use std::ops; use std::{u32, usize}; -use std::cmp; use std::fmt; use std::iter::repeat; use parity_wasm::elements::Local; @@ -1262,13 +1261,15 @@ impl ValueStack { #[inline] fn extend(&mut self, values: &[RuntimeValue]) -> Result<(), TrapKind> { - let len = cmp::min(values.len(), self.buf.len() - self.sp); - self.buf[self.sp..(self.sp+len)].copy_from_slice(&values[..len]); - self.sp += len; - if len < values.len() { - Err(TrapKind::StackOverflow) + let avail_len = self.buf.len() - self.sp; + let to_copy_len = values.len(); + + if to_copy_len <= avail_len { + self.buf[self.sp..(self.sp+to_copy_len)].copy_from_slice(&values[..to_copy_len]); + self.sp += to_copy_len; + Ok(()) } else { - Ok(()) + Err(TrapKind::StackOverflow) } } @@ -1286,8 +1287,13 @@ mod tests { #[test] fn test_stack_extend() { let mut stack = ValueStack::with_limit(5); - let values = vec![RuntimeValue::I32(1), RuntimeValue::I32(2), RuntimeValue::I32(3), - RuntimeValue::I32(4), RuntimeValue::I32(5)]; + let values = vec![ + RuntimeValue::I32(1), + RuntimeValue::I32(2), + RuntimeValue::I32(3), + RuntimeValue::I32(4), + RuntimeValue::I32(5) + ]; assert!(stack.extend(&values).is_ok()); assert_eq!(stack.len(), 5); @@ -1303,4 +1309,28 @@ mod tests { assert_eq!(stack.len(), 0); } + + #[test] + fn test_stack_extend_overflow() { + let mut stack = ValueStack::with_limit(4); + let values = vec![ + RuntimeValue::I32(1), + RuntimeValue::I32(2), + RuntimeValue::I32(3), + RuntimeValue::I32(4), + RuntimeValue::I32(5) + ]; + + assert!(stack.extend(&values).is_err()); + assert_eq!(stack.len(), 0); + + assert!(stack.push(RuntimeValue::I32(6)).is_ok()); + + assert_eq!(stack.len(), 1); + + // check each elements + assert_eq!(stack.pop(), RuntimeValue::I32(6)); + + assert_eq!(stack.len(), 0); + } }