Make Module::new perform validation. (#621)
* Make `Module::new` perform validation. As noticed in #602, `Module::new` did not perform validation, which turns out to be error-prone in practice. Rename it to `Module::new_unchecked`, and add a new `Module::new` which does perform validation. Preserve wasm-c-api's `wasm_module_new`'s behavior by using `Module::new_unchecked`, and implement `wasm_module_validate`. * Change `validate`'s store argument to `&HostRef<Store>`. * Enable multi-value in validation.
This commit is contained in:
committed by
Yury Delendik
parent
e71ab6b846
commit
16b8b3e58d
@@ -4,8 +4,11 @@ use crate::types::{
|
|||||||
ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability,
|
ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability,
|
||||||
TableType, ValType,
|
TableType, ValType,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::{Error, Result};
|
||||||
use wasmparser::{validate, ExternalKind, ImportSectionEntryType, ModuleReader, SectionCode};
|
use wasmparser::{
|
||||||
|
validate, ExternalKind, ImportSectionEntryType, ModuleReader, OperatorValidatorConfig,
|
||||||
|
SectionCode, ValidatingParserConfig,
|
||||||
|
};
|
||||||
|
|
||||||
fn into_memory_type(mt: wasmparser::MemoryType) -> MemoryType {
|
fn into_memory_type(mt: wasmparser::MemoryType) -> MemoryType {
|
||||||
assert!(!mt.shared);
|
assert!(!mt.shared);
|
||||||
@@ -184,7 +187,15 @@ pub struct Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
|
/// Validate and decode the raw wasm data in `binary` and create a new
|
||||||
|
/// `Module` in the given `store`.
|
||||||
pub fn new(store: &HostRef<Store>, binary: &[u8]) -> Result<Module> {
|
pub fn new(store: &HostRef<Store>, binary: &[u8]) -> Result<Module> {
|
||||||
|
Self::validate(store, binary)?;
|
||||||
|
Self::new_unchecked(store, binary)
|
||||||
|
}
|
||||||
|
/// Similar to `new`, but does not perform any validation. Only use this
|
||||||
|
/// on modules which are known to have been validated already!
|
||||||
|
pub fn new_unchecked(store: &HostRef<Store>, binary: &[u8]) -> Result<Module> {
|
||||||
let (imports, exports) = read_imports_and_exports(binary)?;
|
let (imports, exports) = read_imports_and_exports(binary)?;
|
||||||
Ok(Module {
|
Ok(Module {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
@@ -199,8 +210,17 @@ impl Module {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn validate(_store: &Store, binary: &[u8]) -> bool {
|
pub fn validate(_store: &HostRef<Store>, binary: &[u8]) -> Result<()> {
|
||||||
validate(binary, None).is_ok()
|
let config = ValidatingParserConfig {
|
||||||
|
operator_config: OperatorValidatorConfig {
|
||||||
|
enable_threads: false,
|
||||||
|
enable_reference_types: false,
|
||||||
|
enable_bulk_memory: false,
|
||||||
|
enable_simd: false,
|
||||||
|
enable_multi_value: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
validate(binary, Some(config)).map_err(Error::new)
|
||||||
}
|
}
|
||||||
pub fn imports(&self) -> &[ImportType] {
|
pub fn imports(&self) -> &[ImportType] {
|
||||||
&self.imports
|
&self.imports
|
||||||
|
|||||||
@@ -722,6 +722,8 @@ impl wasm_name_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Note that this function does not perform validation on the wasm
|
||||||
|
/// binary. To perform validation, use `wasm_module_validate`.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_module_new(
|
pub unsafe extern "C" fn wasm_module_new(
|
||||||
store: *mut wasm_store_t,
|
store: *mut wasm_store_t,
|
||||||
@@ -729,7 +731,7 @@ pub unsafe extern "C" fn wasm_module_new(
|
|||||||
) -> *mut wasm_module_t {
|
) -> *mut wasm_module_t {
|
||||||
let binary = (*binary).as_slice();
|
let binary = (*binary).as_slice();
|
||||||
let store = &(*store).store;
|
let store = &(*store).store;
|
||||||
let module = Module::new(store, binary).expect("module");
|
let module = Module::new_unchecked(store, binary).expect("module");
|
||||||
let imports = module
|
let imports = module
|
||||||
.imports()
|
.imports()
|
||||||
.iter()
|
.iter()
|
||||||
@@ -756,6 +758,16 @@ pub unsafe extern "C" fn wasm_module_new(
|
|||||||
Box::into_raw(module)
|
Box::into_raw(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_module_validate(
|
||||||
|
store: *mut wasm_store_t,
|
||||||
|
binary: *const wasm_byte_vec_t,
|
||||||
|
) -> bool {
|
||||||
|
let binary = (*binary).as_slice();
|
||||||
|
let store = &(*store).store;
|
||||||
|
Module::validate(store, binary).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_store_delete(store: *mut wasm_store_t) {
|
pub unsafe extern "C" fn wasm_store_delete(store: *mut wasm_store_t) {
|
||||||
let _ = Box::from_raw(store);
|
let _ = Box::from_raw(store);
|
||||||
|
|||||||
Reference in New Issue
Block a user