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( let table_inst = module_ref.table_by_index(DEFAULT_TABLE_INDEX).expect(
"Due to validation default table should exists", "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() { for (j, func_idx) in element_segment.members().into_iter().enumerate() {
let func = module_ref.func_by_index(*func_idx).expect( let func = module_ref.func_by_index(*func_idx).expect(
"Due to validation funcs from element segments should exists", "Due to validation funcs from element segments should exists",

View File

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

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