make Module::deserialize's version check optional via Config (#2945)

* make Module::deserialize's version check optional via Config

A SerializedModule contains the CARGO_PKG_VERSION string, which is
checked for equality when loading. This is a great guard-rail but
some users may want to disable this check (e.g. so they can implement
their own versioning scheme)

* rename config to deserialize_check_wasmtime_version

* add test

* fix doc links

* fix

* thank you rustdoc
This commit is contained in:
Pat Hickey
2021-06-04 12:18:02 -07:00
committed by GitHub
parent 357b4c7b60
commit 895ee2b85f
4 changed files with 36 additions and 8 deletions

View File

@@ -291,6 +291,7 @@ pub struct Config {
#[cfg(feature = "async")]
pub(crate) async_stack_size: usize,
pub(crate) async_support: bool,
pub(crate) deserialize_check_wasmtime_version: bool,
}
impl Config {
@@ -326,6 +327,7 @@ impl Config {
#[cfg(feature = "async")]
async_stack_size: 2 << 20,
async_support: false,
deserialize_check_wasmtime_version: true,
};
ret.cranelift_debug_verifier(false);
ret.cranelift_opt_level(OptLevel::Speed);
@@ -1093,6 +1095,20 @@ impl Config {
self
}
/// Configure whether deserialized modules should validate version
/// information. This only effects [`crate::Module::deserialize()`], which is
/// used to load compiled code from trusted sources. When true,
/// [`crate::Module::deserialize()`] verifies that the wasmtime crate's
/// `CARGO_PKG_VERSION` matches with the version in the binary, which was
/// produced by [`crate::Module::serialize`] or
/// [`crate::Engine::precompile_module`].
///
/// This value defaults to true.
pub fn deserialize_check_wasmtime_version(&mut self, check: bool) -> &mut Self {
self.deserialize_check_wasmtime_version = check;
self
}
pub(crate) fn target_isa(&self) -> Box<dyn TargetIsa> {
self.isa_flags
.clone()

View File

@@ -356,7 +356,10 @@ impl Module {
/// blobs across versions of wasmtime you can be safely guaranteed that
/// future versions of wasmtime will reject old cache entries).
pub unsafe fn deserialize(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Module> {
let module = SerializedModule::from_bytes(bytes.as_ref())?;
let module = SerializedModule::from_bytes(
bytes.as_ref(),
engine.config().deserialize_check_wasmtime_version,
)?;
module.into_module(engine)
}

View File

@@ -329,7 +329,7 @@ impl<'a> SerializedModule<'a> {
Ok(bytes)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
pub fn from_bytes(bytes: &[u8], check_version: bool) -> Result<Self> {
if !bytes.starts_with(HEADER) {
bail!("bytes are not a compatible serialized wasmtime module");
}
@@ -345,12 +345,14 @@ impl<'a> SerializedModule<'a> {
bail!("serialized data is malformed");
}
let version = std::str::from_utf8(&bytes[1..1 + version_len])?;
if version != env!("CARGO_PKG_VERSION") {
bail!(
"Module was compiled with incompatible Wasmtime version '{}'",
version
);
if check_version {
let version = std::str::from_utf8(&bytes[1..1 + version_len])?;
if version != env!("CARGO_PKG_VERSION") {
bail!(
"Module was compiled with incompatible Wasmtime version '{}'",
version
);
}
}
Ok(bincode_options()