mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-13 13:58:38 +00:00
Validate that CPU features are supported when instantiating a module
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -2900,6 +2900,7 @@ name = "wasmer-engine"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"enumset",
|
||||
"lazy_static",
|
||||
"loupe",
|
||||
"memmap2",
|
||||
@@ -2919,6 +2920,7 @@ name = "wasmer-engine-dummy"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"enumset",
|
||||
"loupe",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
@@ -2933,6 +2935,7 @@ name = "wasmer-engine-dylib"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"enumset",
|
||||
"leb128",
|
||||
"libloading",
|
||||
"loupe",
|
||||
@@ -2954,6 +2957,7 @@ version = "2.0.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"cfg-if 1.0.0",
|
||||
"enumset",
|
||||
"leb128",
|
||||
"libloading",
|
||||
"loupe",
|
||||
@@ -2972,6 +2976,7 @@ name = "wasmer-engine-universal"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"enumset",
|
||||
"leb128",
|
||||
"loupe",
|
||||
"region",
|
||||
|
||||
@@ -58,6 +58,11 @@ pub enum InstantiationError {
|
||||
#[error(transparent)]
|
||||
Start(RuntimeError),
|
||||
|
||||
/// The module was compiled with a CPU feature that is not available on
|
||||
/// the current host.
|
||||
#[error("missing requires CPU features: {0:?}")]
|
||||
CpuFeature(String),
|
||||
|
||||
/// Error occurred when initializing the host environment.
|
||||
#[error(transparent)]
|
||||
HostEnvInitialization(HostEnvInitError),
|
||||
@@ -68,6 +73,7 @@ impl From<wasmer_engine::InstantiationError> for InstantiationError {
|
||||
match other {
|
||||
wasmer_engine::InstantiationError::Link(e) => Self::Link(e),
|
||||
wasmer_engine::InstantiationError::Start(e) => Self::Start(e),
|
||||
wasmer_engine::InstantiationError::CpuFeature(e) => Self::CpuFeature(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,12 @@ pub unsafe extern "C" fn wasm_instance_new(
|
||||
return None;
|
||||
}
|
||||
|
||||
Err(e @ InstantiationError::CpuFeature(_)) => {
|
||||
crate::error::update_last_error(e.to_string());
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
Err(InstantiationError::HostEnvInitialization(error)) => {
|
||||
crate::error::update_last_error(error);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ tempfile = "3.1"
|
||||
which = "4.0"
|
||||
rkyv = "0.6.1"
|
||||
loupe = "0.1"
|
||||
enumset = "1.0"
|
||||
|
||||
[features]
|
||||
# Enable the `compiler` feature if you want the engine to compile
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::engine::{DylibEngine, DylibEngineInner};
|
||||
use crate::serialize::{ArchivedModuleMetadata, ModuleMetadata};
|
||||
use enumset::EnumSet;
|
||||
use libloading::{Library, Symbol as LibrarySymbol};
|
||||
use loupe::MemoryUsage;
|
||||
use std::error::Error;
|
||||
@@ -17,8 +18,8 @@ use tracing::log::error;
|
||||
#[cfg(feature = "compiler")]
|
||||
use tracing::trace;
|
||||
use wasmer_compiler::{
|
||||
Architecture, CompileError, CompiledFunctionFrameInfo, Features, FunctionAddressMap,
|
||||
OperatingSystem, Symbol, SymbolRegistry, Triple,
|
||||
Architecture, CompileError, CompiledFunctionFrameInfo, CpuFeature, Features,
|
||||
FunctionAddressMap, OperatingSystem, Symbol, SymbolRegistry, Triple,
|
||||
};
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::{
|
||||
@@ -211,6 +212,7 @@ impl DylibArtifact {
|
||||
prefix: engine_inner.get_prefix(&data),
|
||||
data_initializers,
|
||||
function_body_lengths,
|
||||
cpu_features: target.cpu_features().as_u64(),
|
||||
};
|
||||
|
||||
let serialized_data = metadata.serialize()?;
|
||||
@@ -800,6 +802,10 @@ impl Artifact for DylibArtifact {
|
||||
&self.metadata.compile_info.features
|
||||
}
|
||||
|
||||
fn cpu_features(&self) -> enumset::EnumSet<CpuFeature> {
|
||||
EnumSet::from_u64(self.metadata.cpu_features)
|
||||
}
|
||||
|
||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||
&*self.metadata.data_initializers
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ pub struct ModuleMetadata {
|
||||
pub data_initializers: Box<[OwnedDataInitializer]>,
|
||||
// The function body lengths (used to find function by address)
|
||||
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
|
||||
pub cpu_features: u64,
|
||||
}
|
||||
|
||||
pub struct ModuleMetadataSymbolRegistry<'a> {
|
||||
|
||||
@@ -24,6 +24,7 @@ leb128 = "0.2"
|
||||
libloading = "0.7"
|
||||
tempfile = "3.1"
|
||||
loupe = "0.1"
|
||||
enumset = "1.0"
|
||||
|
||||
[features]
|
||||
# Enable the `compiler` feature if you want the engine to compile
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
|
||||
use crate::engine::{StaticlibEngine, StaticlibEngineInner};
|
||||
use crate::serialize::{ModuleMetadata, ModuleMetadataSymbolRegistry};
|
||||
use enumset::EnumSet;
|
||||
use loupe::MemoryUsage;
|
||||
use std::collections::BTreeMap;
|
||||
use std::error::Error;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use wasmer_compiler::{CompileError, Features, OperatingSystem, SymbolRegistry, Triple};
|
||||
use wasmer_compiler::{
|
||||
CompileError, CpuFeature, Features, OperatingSystem, SymbolRegistry, Triple,
|
||||
};
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::{
|
||||
CompileModuleInfo, Compiler, FunctionBodyData, ModuleEnvironment, ModuleMiddlewareChain,
|
||||
@@ -182,6 +185,7 @@ impl StaticlibArtifact {
|
||||
prefix: engine_inner.get_prefix(&data),
|
||||
data_initializers,
|
||||
function_body_lengths,
|
||||
cpu_features: target.cpu_features().as_u64(),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -453,6 +457,10 @@ impl Artifact for StaticlibArtifact {
|
||||
&self.metadata.compile_info.features
|
||||
}
|
||||
|
||||
fn cpu_features(&self) -> EnumSet<CpuFeature> {
|
||||
EnumSet::from_u64(self.metadata.cpu_features)
|
||||
}
|
||||
|
||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||
&*self.metadata.data_initializers
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ pub struct ModuleMetadata {
|
||||
pub data_initializers: Box<[OwnedDataInitializer]>,
|
||||
// The function body lengths (used to find function by address)
|
||||
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
|
||||
pub cpu_features: u64,
|
||||
}
|
||||
|
||||
#[derive(MemoryUsage)]
|
||||
|
||||
@@ -11,8 +11,13 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmer-types = { path = "../types", version = "2.0.0", features = ["enable-rkyv"] }
|
||||
wasmer-compiler = { path = "../compiler", version = "2.0.0", features = ["translator", "enable-rkyv"] }
|
||||
wasmer-types = { path = "../types", version = "2.0.0", features = [
|
||||
"enable-rkyv",
|
||||
] }
|
||||
wasmer-compiler = { path = "../compiler", version = "2.0.0", features = [
|
||||
"translator",
|
||||
"enable-rkyv",
|
||||
] }
|
||||
wasmer-vm = { path = "../vm", version = "2.0.0", features = ["enable-rkyv"] }
|
||||
wasmer-engine = { path = "../engine", version = "2.0.0" }
|
||||
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
||||
@@ -21,6 +26,7 @@ cfg-if = "1.0"
|
||||
leb128 = "0.2"
|
||||
rkyv = "0.6.1"
|
||||
loupe = "0.1"
|
||||
enumset = "1.0"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3", features = ["winnt", "impl-default"] }
|
||||
|
||||
@@ -6,9 +6,10 @@ use crate::link::link_module;
|
||||
#[cfg(feature = "compiler")]
|
||||
use crate::serialize::SerializableCompilation;
|
||||
use crate::serialize::SerializableModule;
|
||||
use enumset::EnumSet;
|
||||
use loupe::MemoryUsage;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wasmer_compiler::{CompileError, Features, Triple};
|
||||
use wasmer_compiler::{CompileError, CpuFeature, Features, Triple};
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment, ModuleMiddlewareChain};
|
||||
use wasmer_engine::{
|
||||
@@ -128,6 +129,7 @@ impl UniversalArtifact {
|
||||
compilation: serializable_compilation,
|
||||
compile_info,
|
||||
data_initializers,
|
||||
cpu_features: engine.target().cpu_features().as_u64(),
|
||||
};
|
||||
Self::from_parts(&mut inner_engine, serializable)
|
||||
}
|
||||
@@ -307,6 +309,10 @@ impl Artifact for UniversalArtifact {
|
||||
&self.serializable.compile_info.features
|
||||
}
|
||||
|
||||
fn cpu_features(&self) -> EnumSet<CpuFeature> {
|
||||
EnumSet::from_u64(self.serializable.cpu_features)
|
||||
}
|
||||
|
||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||
&*self.serializable.data_initializers
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct SerializableModule {
|
||||
pub compilation: SerializableCompilation,
|
||||
pub compile_info: CompileModuleInfo,
|
||||
pub data_initializers: Box<[OwnedDataInitializer]>,
|
||||
pub cpu_features: u64,
|
||||
}
|
||||
|
||||
fn to_serialize_error(err: impl std::error::Error) -> SerializeError {
|
||||
|
||||
@@ -25,6 +25,7 @@ serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_bytes = { version = "0.11" }
|
||||
lazy_static = "1.4"
|
||||
loupe = "0.1"
|
||||
enumset = "1.0"
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use crate::{
|
||||
resolve_imports, InstantiationError, Resolver, RuntimeError, SerializeError, Tunables,
|
||||
};
|
||||
use enumset::EnumSet;
|
||||
use loupe::MemoryUsage;
|
||||
use std::any::Any;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use wasmer_compiler::Features;
|
||||
use wasmer_compiler::{CpuFeature, Features};
|
||||
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
||||
use wasmer_types::{
|
||||
DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo,
|
||||
@@ -43,6 +44,9 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
|
||||
/// Returns the features for this Artifact
|
||||
fn features(&self) -> &Features;
|
||||
|
||||
/// Returns the CPU features for this Artifact
|
||||
fn cpu_features(&self) -> EnumSet<CpuFeature>;
|
||||
|
||||
/// Returns the memory styles associated with this `Artifact`.
|
||||
fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle>;
|
||||
|
||||
@@ -96,6 +100,16 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
|
||||
resolver: &dyn Resolver,
|
||||
host_state: Box<dyn Any>,
|
||||
) -> Result<InstanceHandle, InstantiationError> {
|
||||
// Validate the CPU features this module was compiled with against the
|
||||
// host CPU features.
|
||||
let host_cpu_features = CpuFeature::for_host();
|
||||
if !host_cpu_features.is_superset(self.cpu_features()) {
|
||||
Err(InstantiationError::CpuFeature(format!(
|
||||
"{:?}",
|
||||
self.cpu_features().difference(host_cpu_features)
|
||||
)))?;
|
||||
}
|
||||
|
||||
self.preinstantiate()?;
|
||||
|
||||
let module = self.module();
|
||||
|
||||
@@ -91,6 +91,11 @@ pub enum InstantiationError {
|
||||
#[error(transparent)]
|
||||
Link(LinkError),
|
||||
|
||||
/// The module was compiled with a CPU feature that is not available on
|
||||
/// the current host.
|
||||
#[error("module compiled with CPU feature that is missing from host")]
|
||||
CpuFeature(String),
|
||||
|
||||
/// A runtime error occured while invoking the start function
|
||||
#[error(transparent)]
|
||||
Start(RuntimeError),
|
||||
|
||||
@@ -257,7 +257,9 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> {
|
||||
.err()
|
||||
.unwrap();
|
||||
match err {
|
||||
InstantiationError::Link(_) | InstantiationError::HostEnvInitialization(_) => {
|
||||
InstantiationError::Link(_)
|
||||
| InstantiationError::HostEnvInitialization(_)
|
||||
| InstantiationError::CpuFeature(_) => {
|
||||
panic!("It should be a start error")
|
||||
}
|
||||
InstantiationError::Start(err) => {
|
||||
|
||||
@@ -16,19 +16,14 @@ serde = { version = "1.0", features = ["derive", "rc"], optional = true }
|
||||
serde_bytes = { version = "0.11", optional = true }
|
||||
bincode = { version = "1.2", optional = true }
|
||||
loupe = "0.1"
|
||||
enumset = "1.0"
|
||||
|
||||
[features]
|
||||
# Enable the `compiler` feature if you want the engine to compile
|
||||
# and not be only on headless mode.
|
||||
default = ["serialize", "compiler"]
|
||||
compiler = [
|
||||
"wasmer-compiler/translator"
|
||||
]
|
||||
serialize = [
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"bincode"
|
||||
]
|
||||
compiler = ["wasmer-compiler/translator"]
|
||||
serialize = ["serde", "serde_bytes", "bincode"]
|
||||
|
||||
[badges]
|
||||
# TODO: publish this crate again and deprecate it
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
//! done as separate steps.
|
||||
|
||||
use crate::engine::DummyEngine;
|
||||
use enumset::EnumSet;
|
||||
use loupe::MemoryUsage;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use wasmer_compiler::CompileError;
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::ModuleEnvironment;
|
||||
use wasmer_compiler::{CompileError, CpuFeature};
|
||||
use wasmer_engine::{Artifact, DeserializeError, Engine as _, SerializeError, Tunables};
|
||||
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
||||
use wasmer_types::{
|
||||
@@ -30,6 +31,7 @@ pub struct DummyArtifactMetadata {
|
||||
// Plans for that module
|
||||
pub memory_styles: PrimaryMap<MemoryIndex, MemoryStyle>,
|
||||
pub table_styles: PrimaryMap<TableIndex, TableStyle>,
|
||||
pub cpu_features: u64,
|
||||
}
|
||||
|
||||
/// A Dummy artifact.
|
||||
@@ -104,6 +106,7 @@ impl DummyArtifact {
|
||||
data_initializers,
|
||||
memory_styles,
|
||||
table_styles,
|
||||
cpu_features: engine.target().cpu_features().as_u64(),
|
||||
};
|
||||
Self::from_parts(&engine, metadata)
|
||||
}
|
||||
@@ -211,6 +214,10 @@ impl Artifact for DummyArtifact {
|
||||
&self.metadata.features
|
||||
}
|
||||
|
||||
fn cpu_features(&self) -> EnumSet<CpuFeature> {
|
||||
EnumSet::from_u64(self.metadata.cpu_features)
|
||||
}
|
||||
|
||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||
&*self.metadata.data_initializers
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user