From 9dd7a5dfaf09d584936c90b5810485cbf5ea1544 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Mon, 18 Dec 2017 15:34:17 +0300 Subject: [PATCH] Check global's type on instantiation. --- src/interpreter/global.rs | 14 +++++++++++--- src/interpreter/module.rs | 10 ++++++++-- src/interpreter/runner.rs | 5 ++--- src/interpreter/value.rs | 10 +++++----- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/interpreter/global.rs b/src/interpreter/global.rs index 572dab7..6df7371 100644 --- a/src/interpreter/global.rs +++ b/src/interpreter/global.rs @@ -1,4 +1,5 @@ use std::cell::Cell; +use elements::ValueType; use interpreter::value::RuntimeValue; use interpreter::Error; @@ -17,9 +18,8 @@ impl GlobalInstance { } pub fn set(&self, val: RuntimeValue) -> Result<(), Error> { - if !self.mutable { - return Err(Error::Validation("Can't set immutable global".into())); - } + assert!(self.mutable, "Attempt to change an immutable variable"); + assert!(self.value_type() == val.value_type(), "Attempt to change variable type"); self.val.set(val); Ok(()) } @@ -27,4 +27,12 @@ impl GlobalInstance { pub fn get(&self) -> RuntimeValue { self.val.get() } + + pub fn is_mutable(&self) -> bool { + self.mutable + } + + pub fn value_type(&self) -> ValueType { + self.val.get().value_type() + } } diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index c400627..ee923cc 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -198,8 +198,14 @@ impl ModuleInstance { match_limits(memory.limits(), mt.limits())?; instance.push_memory(Rc::clone(memory)); } - (&External::Global(ref _gl), &ExternVal::Global(ref global)) => { - // TODO: check globals + (&External::Global(ref gl), &ExternVal::Global(ref global)) => { + if gl.content_type() != global.value_type() { + return Err(Error::Initialization(format!( + "Expect global with {:?} type, but provided global with {:?} type", + gl.content_type(), + global.value_type(), + ))); + } instance.push_global(Rc::clone(global)) } (expected_import, actual_extern_val) => { diff --git a/src/interpreter/runner.rs b/src/interpreter/runner.rs index 01cb0f7..2590ae7 100644 --- a/src/interpreter/runner.rs +++ b/src/interpreter/runner.rs @@ -1149,11 +1149,10 @@ fn effective_address(address: u32, offset: u32) -> Result { } pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit) -> Result, Error> { - let mut args = function_type.params().iter().rev().map(|param_type| { + let mut args = function_type.params().iter().cloned().rev().map(|expected_type| { let param_value = caller_stack.pop()?; let actual_type = param_value.value_type(); - let expected_type = (*param_type).into(); - if actual_type != Some(expected_type) { + if actual_type != expected_type { return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type))); } diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index 4b7b94a..bc8cf43 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -131,12 +131,12 @@ impl RuntimeValue { } /// Get variable type for this value. - pub fn value_type(&self) -> Option { + pub fn value_type(&self) -> ValueType { match *self { - RuntimeValue::I32(_) => Some(ValueType::I32), - RuntimeValue::I64(_) => Some(ValueType::I64), - RuntimeValue::F32(_) => Some(ValueType::F32), - RuntimeValue::F64(_) => Some(ValueType::F64), + RuntimeValue::I32(_) => ValueType::I32, + RuntimeValue::I64(_) => ValueType::I64, + RuntimeValue::F32(_) => ValueType::F32, + RuntimeValue::F64(_) => ValueType::F64, } } }