Update spec testsuite; Fix instantiation bug (#61)

The bug was about instantiating a module with elements segment being out-of-bounds, however, it was with zero length. E.g.:

```
(module
  (table 0 anyfunc)
  (elem (i32.const 1))
)
```

In our impl there was no out-of-bounds, because there was no attempt to set any table entry.

This change adds early check for specifically this case.
This commit is contained in:
Sergey Pepyakin 2018-02-19 18:59:18 +03:00 committed by Nikolay Volf
parent d02b0f8527
commit 9140e869e2
3 changed files with 42 additions and 31 deletions

View File

@ -403,6 +403,15 @@ impl ModuleInstance {
let table_inst = module_ref.table_by_index(DEFAULT_TABLE_INDEX).expect(
"Due to validation default table should exists",
);
// This check is not only for bailing out early, but also to check the case when
// segment consist of 0 members.
if offset_val as usize + element_segment.members().len() > table_inst.current_size() as usize {
return Err(
Error::Instantiation("elements segment does not fit".to_string())
);
}
for (j, func_idx) in element_segment.members().into_iter().enumerate() {
let func = module_ref.func_by_index(*func_idx).expect(
"Due to validation funcs from element segments should exists",

View File

@ -7,7 +7,7 @@ use wasmi::{
GlobalInstance, GlobalRef, ImportResolver, ImportsBuilder, MemoryDescriptor,
MemoryInstance, MemoryRef, Module, ModuleImportResolver, ModuleInstance, ModuleRef,
RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableInstance, TableRef, Trap,
ValueType};
};
use wasmi::memory_units::Pages;
use wabt::script::{self, Action, Command, CommandKind, ScriptParser, Value};
@ -44,7 +44,6 @@ struct SpecModule {
table: TableRef,
memory: MemoryRef,
global_i32: GlobalRef,
global_i64: GlobalRef,
global_f32: GlobalRef,
global_f64: GlobalRef,
}
@ -55,7 +54,6 @@ impl SpecModule {
table: TableInstance::alloc(10, Some(20)).unwrap(),
memory: MemoryInstance::alloc(Pages(1), Some(Pages(2))).unwrap(),
global_i32: GlobalInstance::alloc(RuntimeValue::I32(666), false),
global_i64: GlobalInstance::alloc(RuntimeValue::I64(666), false),
global_f32: GlobalInstance::alloc(RuntimeValue::F32(666.0), false),
global_f64: GlobalInstance::alloc(RuntimeValue::F64(666.0), false),
}
@ -86,41 +84,45 @@ impl ModuleImportResolver for SpecModule {
field_name: &str,
func_type: &Signature,
) -> Result<FuncRef, InterpreterError> {
if field_name == "print" {
if func_type.return_type().is_some() {
return Err(InterpreterError::Instantiation(
"Function `print` have unit return type".into(),
));
}
let index = match field_name {
"print" => PRINT_FUNC_INDEX,
"print_i32" => PRINT_FUNC_INDEX,
"print_i32_f32" => PRINT_FUNC_INDEX,
"print_f64_f64" => PRINT_FUNC_INDEX,
"print_f32" => PRINT_FUNC_INDEX,
"print_f64" => PRINT_FUNC_INDEX,
_ => {
return Err(InterpreterError::Instantiation(format!(
"Unknown host func import {}",
field_name
)));
}
};
let func = FuncInstance::alloc_host(func_type.clone(), PRINT_FUNC_INDEX);
return Ok(func);
}
if func_type.return_type().is_some() {
return Err(InterpreterError::Instantiation(
"Function `print_` have unit return type".into(),
));
}
Err(InterpreterError::Instantiation(format!(
"Unknown host func import {}",
field_name
)))
let func = FuncInstance::alloc_host(func_type.clone(), index);
return Ok(func);
}
fn resolve_global(
&self,
field_name: &str,
global_type: &GlobalDescriptor,
_global_type: &GlobalDescriptor,
) -> Result<GlobalRef, InterpreterError> {
if field_name == "global" {
return match global_type.value_type() {
ValueType::I32 => Ok(self.global_i32.clone()),
ValueType::I64 => Ok(self.global_i64.clone()),
ValueType::F32 => Ok(self.global_f32.clone()),
ValueType::F64 => Ok(self.global_f64.clone()),
};
}
Err(InterpreterError::Instantiation(format!(
"Unknown host global import {}",
field_name
)))
match field_name {
"global_i32" => Ok(self.global_i32.clone()),
"global_f32" => Ok(self.global_f32.clone()),
"global_f64" => Ok(self.global_f64.clone()),
_ => Err(InterpreterError::Instantiation(format!(
"Unknown host global import {}",
field_name
)))
}
}
fn resolve_memory(

@ -1 +1 @@
Subproject commit b38bf51ea9c956951b9466aa8243d9727d009bb2
Subproject commit c538faa43217146f458b9bc2d4b704d0a4d80963