feat: Implement safe, checked module artifact deserialization

Enable rkyv validation of serialized module artifacts.

Required additions:
* derive the required CheckBytes trait for all types
* Add `_checked` variants of all the deserialization functions

Also enables the `strict` feature of rkyv by default.
This will ensure consistent archive binary layout across architectures
and Rust compiler versions.
This commit is contained in:
Christoph Herzog
2023-03-31 11:54:10 +02:00
committed by Christoph Herzog
parent 9cb4bf32c9
commit 47cc5bbf99
29 changed files with 327 additions and 28 deletions

1
Cargo.lock generated
View File

@@ -5709,6 +5709,7 @@ dependencies = [
name = "wasmer-types" name = "wasmer-types"
version = "3.2.0-beta.1" version = "3.2.0-beta.1"
dependencies = [ dependencies = [
"bytecheck",
"enum-iterator", "enum-iterator",
"enumset", "enumset",
"indexmap", "indexmap",

View File

@@ -238,6 +238,18 @@ impl Module {
return Err(DeserializeError::Generic("You need to enable the `js-serializable-module` feature flag to deserialize a `Module`".to_string())); return Err(DeserializeError::Generic("You need to enable the `js-serializable-module` feature flag to deserialize a `Module`".to_string()));
} }
pub fn deserialize_checked(
_engine: &impl AsEngineRef,
_bytes: impl IntoBytes,
) -> Result<Self, DeserializeError> {
#[cfg(feature = "js-serializable-module")]
return Self::from_binary(_engine, &_bytes.into_bytes())
.map_err(|e| DeserializeError::Compiler(e));
#[cfg(not(feature = "js-serializable-module"))]
return Err(DeserializeError::Generic("You need to enable the `js-serializable-module` feature flag to deserialize a `Module`".to_string()));
}
pub unsafe fn deserialize_from_file( pub unsafe fn deserialize_from_file(
engine: &impl AsEngineRef, engine: &impl AsEngineRef,
path: impl AsRef<Path>, path: impl AsRef<Path>,
@@ -246,6 +258,14 @@ impl Module {
Self::deserialize(engine, bytes) Self::deserialize(engine, bytes)
} }
pub fn deserialize_from_file_checked(
engine: &impl AsEngineRef,
path: impl AsRef<Path>,
) -> Result<Self, DeserializeError> {
let bytes = std::fs::read(path.as_ref())?;
Self::deserialize_checked(engine, bytes)
}
pub fn set_name(&mut self, name: &str) -> bool { pub fn set_name(&mut self, name: &str) -> bool {
self.name = Some(name.to_string()); self.name = Some(name.to_string());
true true

View File

@@ -219,6 +219,8 @@ impl Module {
/// Deserializes a serialized Module binary into a `Module`. /// Deserializes a serialized Module binary into a `Module`.
/// ///
/// Note: You should usually prefer the safe [`Module::deserialize_checked`].
///
/// # Important /// # Important
/// ///
/// This function only accepts a custom binary format, which will be different /// This function only accepts a custom binary format, which will be different
@@ -253,6 +255,56 @@ impl Module {
Ok(Self(module_imp::Module::deserialize(engine, bytes)?)) Ok(Self(module_imp::Module::deserialize(engine, bytes)?))
} }
/// Deserializes a serialized Module binary into a `Module`.
///
/// # Important
///
/// This function only accepts a custom binary format, which will be different
/// than the `wasm` binary format and may change among Wasmer versions.
/// (it should be the result of the serialization of a Module via the
/// `Module::serialize` method.).
///
/// # Usage
///
/// ```ignore
/// # use wasmer::*;
/// # fn main() -> anyhow::Result<()> {
/// # let mut store = Store::default();
/// let module = Module::deserialize_checked(&store, serialized_data)?;
/// # Ok(())
/// # }
/// ```
pub fn deserialize_checked(
engine: &impl AsEngineRef,
bytes: impl IntoBytes,
) -> Result<Self, DeserializeError> {
Ok(Self(module_imp::Module::deserialize_checked(
engine, bytes,
)?))
}
/// Deserializes a a serialized Module located in a `Path` into a `Module`.
/// > Note: the module has to be serialized before with the `serialize` method.
///
/// # Usage
///
/// ```ignore
/// # use wasmer::*;
/// # let mut store = Store::default();
/// # fn main() -> anyhow::Result<()> {
/// let module = Module::deserialize_from_file(&store, path)?;
/// # Ok(())
/// # }
/// ```
pub fn deserialize_from_file_checked(
engine: &impl AsEngineRef,
path: impl AsRef<Path>,
) -> Result<Self, DeserializeError> {
Ok(Self(module_imp::Module::deserialize_from_file_checked(
engine, path,
)?))
}
/// Deserializes a a serialized Module located in a `Path` into a `Module`. /// Deserializes a a serialized Module located in a `Path` into a `Module`.
/// > Note: the module has to be serialized before with the `serialize` method. /// > Note: the module has to be serialized before with the `serialize` method.
/// ///

View File

@@ -78,6 +78,19 @@ impl Module {
Ok(Self::from_artifact(artifact)) Ok(Self::from_artifact(artifact))
} }
pub fn deserialize_checked(
engine: &impl AsEngineRef,
bytes: impl IntoBytes,
) -> Result<Self, DeserializeError> {
let bytes = bytes.into_bytes();
let artifact = engine
.as_engine_ref()
.engine()
.0
.deserialize_checked(&bytes)?;
Ok(Self::from_artifact(artifact))
}
pub unsafe fn deserialize_from_file( pub unsafe fn deserialize_from_file(
engine: &impl AsEngineRef, engine: &impl AsEngineRef,
path: impl AsRef<Path>, path: impl AsRef<Path>,
@@ -90,6 +103,18 @@ impl Module {
Ok(Self::from_artifact(artifact)) Ok(Self::from_artifact(artifact))
} }
pub fn deserialize_from_file_checked(
engine: &impl AsEngineRef,
path: impl AsRef<Path>,
) -> Result<Self, DeserializeError> {
let artifact = engine
.as_engine_ref()
.engine()
.0
.deserialize_from_file_checked(path.as_ref())?;
Ok(Self::from_artifact(artifact))
}
fn from_artifact(artifact: Arc<Artifact>) -> Self { fn from_artifact(artifact: Arc<Artifact>) -> Self {
Self { artifact } Self { artifact }
} }

View File

@@ -148,6 +148,30 @@ impl Artifact {
/// # Safety /// # Safety
/// This function is unsafe because rkyv reads directly without validating /// This function is unsafe because rkyv reads directly without validating
/// the data. /// the data.
pub fn deserialize_checked(engine: &Engine, bytes: &[u8]) -> Result<Self, DeserializeError> {
if !ArtifactBuild::is_deserializable(bytes) {
return Err(DeserializeError::Incompatible(
"Magic header not found".to_string(),
));
}
let bytes = Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
let metadata_len = MetadataHeader::parse(bytes)?;
let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
let serializable = SerializableModule::deserialize_checked(metadata_slice)?;
let artifact = ArtifactBuild::from_serializable(serializable);
let mut inner_engine = engine.inner_mut();
Self::from_parts(&mut inner_engine, artifact, engine.target())
.map_err(DeserializeError::Compiler)
}
/// Deserialize a ArtifactBuild
///
/// # Safety
/// This function is unsafe because rkyv reads directly without validating the data.
pub unsafe fn deserialize(engine: &Engine, bytes: &[u8]) -> Result<Self, DeserializeError> { pub unsafe fn deserialize(engine: &Engine, bytes: &[u8]) -> Result<Self, DeserializeError> {
if !ArtifactBuild::is_deserializable(bytes) { if !ArtifactBuild::is_deserializable(bytes) {
let static_artifact = Self::deserialize_object(engine, bytes); let static_artifact = Self::deserialize_object(engine, bytes);

View File

@@ -200,12 +200,28 @@ impl Engine {
Ok(Arc::new(Artifact::deserialize(self, bytes)?)) Ok(Arc::new(Artifact::deserialize(self, bytes)?))
} }
/// Deserializes a WebAssembly module
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub fn deserialize_checked(&self, bytes: &[u8]) -> Result<Arc<Artifact>, DeserializeError> {
Ok(Arc::new(Artifact::deserialize_checked(self, bytes)?))
}
/// Deserializes a WebAssembly module from a path /// Deserializes a WebAssembly module from a path
#[cfg(not(target_arch = "wasm32"))]
pub fn deserialize_from_file_checked(
&self,
file_ref: &Path,
) -> Result<Arc<Artifact>, DeserializeError> {
let contents = std::fs::read(file_ref)?;
self.deserialize_checked(&contents)
}
/// Deserialize from a file path.
/// ///
/// # Safety /// # Safety
/// ///
/// The file's content must represent a serialized WebAssembly module. /// See [`crate::Module::deserialize_from_file`].
#[cfg(not(target_arch = "wasm32"))]
pub unsafe fn deserialize_from_file( pub unsafe fn deserialize_from_file(
&self, &self,
file_ref: &Path, file_ref: &Path,

View File

@@ -16,10 +16,11 @@ serde_bytes = { version = "0.11", optional = true }
thiserror = "1.0" thiserror = "1.0"
more-asserts = "0.2" more-asserts = "0.2"
indexmap = { version = "1.6" } indexmap = { version = "1.6" }
rkyv = { version = "0.7.40", features = ["indexmap"] } rkyv = { version = "0.7.40", features = ["indexmap", "validation", "strict"] }
enum-iterator = "0.7.0" enum-iterator = "0.7.0"
target-lexicon = { version = "0.12.2", default-features = false } target-lexicon = { version = "0.12.2", default-features = false }
enumset = "1.0" enumset = "1.0"
bytecheck = "0.6.8"
[dev-dependencies] [dev-dependencies]
memoffset = "0.6" memoffset = "0.6"

View File

@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
/// Single source location to generated address mapping. /// Single source location to generated address mapping.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct InstructionAddressMap { pub struct InstructionAddressMap {
/// Original source location. /// Original source location.
pub srcloc: SourceLoc, pub srcloc: SourceLoc,
@@ -24,6 +25,7 @@ pub struct InstructionAddressMap {
/// Function and its instructions addresses mappings. /// Function and its instructions addresses mappings.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct FunctionAddressMap { pub struct FunctionAddressMap {
/// Instructions maps. /// Instructions maps.
/// The array is sorted by the InstructionAddressMap::code_offset field. /// The array is sorted by the InstructionAddressMap::code_offset field.

View File

@@ -21,6 +21,7 @@ use serde::{Deserialize, Serialize};
/// the frame information after a `Trap`. /// the frame information after a `Trap`.
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct CompiledFunctionFrameInfo { pub struct CompiledFunctionFrameInfo {
/// The traps (in the function body). /// The traps (in the function body).
/// ///
@@ -34,6 +35,7 @@ pub struct CompiledFunctionFrameInfo {
/// The function body. /// The function body.
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct FunctionBody { pub struct FunctionBody {
/// The function body bytes. /// The function body bytes.
#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] #[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))]
@@ -50,6 +52,7 @@ pub struct FunctionBody {
/// and unwind information). /// and unwind information).
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct CompiledFunction { pub struct CompiledFunction {
/// The function body. /// The function body.
pub body: FunctionBody, pub body: FunctionBody,
@@ -74,7 +77,9 @@ pub type CustomSections = PrimaryMap<SectionIndex, CustomSection>;
/// In the future this structure may also hold other information useful /// In the future this structure may also hold other information useful
/// for debugging. /// for debugging.
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, PartialEq, Eq, Clone)] #[derive(
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, PartialEq, Eq, Clone,
)]
#[archive(as = "Self")] #[archive(as = "Self")]
pub struct Dwarf { pub struct Dwarf {
/// The section index in the [`Compilation`] that corresponds to the exception frames. /// The section index in the [`Compilation`] that corresponds to the exception frames.

View File

@@ -13,6 +13,7 @@ use std::sync::Arc;
/// or the `MemoryStyle` and `TableStyle`). /// or the `MemoryStyle` and `TableStyle`).
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct CompileModuleInfo { pub struct CompileModuleInfo {
/// The features used for compiling the module /// The features used for compiling the module
pub features: Features, pub features: Features,

View File

@@ -21,8 +21,11 @@ use serde::{Deserialize, Serialize};
/// Relocation kinds for every ISA. /// Relocation kinds for every ISA.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Copy, Clone, Debug, PartialEq, Eq)] #[derive(
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Copy, Clone, Debug, PartialEq, Eq,
)]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum RelocationKind { pub enum RelocationKind {
/// absolute 4-byte /// absolute 4-byte
Abs4, Abs4,
@@ -90,6 +93,7 @@ impl fmt::Display for RelocationKind {
/// A record of a relocation to perform. /// A record of a relocation to perform.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct Relocation { pub struct Relocation {
/// The relocation kind. /// The relocation kind.
pub kind: RelocationKind, pub kind: RelocationKind,
@@ -103,8 +107,11 @@ pub struct Relocation {
/// Destination function. Can be either user function or some special one, like `memory.grow`. /// Destination function. Can be either user function or some special one, like `memory.grow`.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Copy, Clone, PartialEq, Eq)] #[derive(
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, Copy, Clone, PartialEq, Eq,
)]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum RelocationTarget { pub enum RelocationTarget {
/// A relocation to a function defined locally in the wasm (not an imported one). /// A relocation to a function defined locally in the wasm (not an imported one).
LocalFunc(LocalFunctionIndex), LocalFunc(LocalFunctionIndex),

View File

@@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize};
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
Copy, Copy,
Clone, Clone,
PartialEq, PartialEq,
@@ -37,8 +38,11 @@ entity_impl!(SectionIndex);
/// ///
/// Determines how a custom section may be used. /// Determines how a custom section may be used.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, Clone, PartialEq, Eq,
)]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum CustomSectionProtection { pub enum CustomSectionProtection {
/// A custom section with read permission. /// A custom section with read permission.
Read, Read,
@@ -53,6 +57,7 @@ pub enum CustomSectionProtection {
/// in the emitted module. /// in the emitted module.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct CustomSection { pub struct CustomSection {
/// Memory protection that applies to this section. /// Memory protection that applies to this section.
pub protection: CustomSectionProtection, pub protection: CustomSectionProtection,
@@ -72,6 +77,7 @@ pub struct CustomSection {
/// The bytes in the section. /// The bytes in the section.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct SectionBody(#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] Vec<u8>); pub struct SectionBody(#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] Vec<u8>);
impl SectionBody { impl SectionBody {

View File

@@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize};
)] )]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, rkyv::CheckBytes)]
#[archive(as = "Self")] #[archive(as = "Self")]
pub struct SourceLoc(u32); pub struct SourceLoc(u32);

View File

@@ -5,9 +5,9 @@ use crate::{
SectionIndex, SerializeError, SignatureIndex, SectionIndex, SerializeError, SignatureIndex,
}; };
use rkyv::{ use rkyv::{
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer, archived_value, check_archived_value, de::deserializers::SharedDeserializeMap,
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize, ser::serializers::AllocSerializer, ser::Serializer as RkyvSerializer, Archive,
Serialize as RkyvSerialize, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize,
}; };
#[cfg(feature = "enable-serde")] #[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -50,6 +50,7 @@ pub trait SymbolRegistry: Send + Sync {
/// Serializable struct that represents the compiled metadata. /// Serializable struct that represents the compiled metadata.
#[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct ModuleMetadata { pub struct ModuleMetadata {
/// Compile info /// Compile info
pub compile_info: CompileModuleInfo, pub compile_info: CompileModuleInfo,
@@ -114,6 +115,14 @@ impl ModuleMetadata {
Self::deserialize_from_archive(archived) Self::deserialize_from_archive(archived)
} }
/// Deserialize a Module from a slice.
/// The slice must have the following format:
/// RKYV serialization (any length) + POS (8 bytes)
pub fn deserialize_checked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
let archived = Self::archive_from_slice_checked(metadata_slice)?;
Self::deserialize_from_archive(archived)
}
/// # Safety /// # Safety
/// ///
/// This method is unsafe. /// This method is unsafe.
@@ -135,6 +144,25 @@ impl ModuleMetadata {
)) ))
} }
/// # Safety
///
/// This method is unsafe.
/// Please check `ModuleMetadata::deserialize` for more details.
fn archive_from_slice_checked(
metadata_slice: &[u8],
) -> Result<&ArchivedModuleMetadata, DeserializeError> {
if metadata_slice.len() < 8 {
return Err(DeserializeError::Incompatible(
"invalid serialized ModuleMetadata".into(),
));
}
let mut pos: [u8; 8] = Default::default();
pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
let pos: u64 = u64::from_le_bytes(pos);
check_archived_value::<Self>(&metadata_slice[..metadata_slice.len() - 8], pos as usize)
.map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
}
/// Deserialize a compilation module from an archive /// Deserialize a compilation module from an archive
pub fn deserialize_from_archive( pub fn deserialize_from_archive(
archived: &ArchivedModuleMetadata, archived: &ArchivedModuleMetadata,

View File

@@ -7,7 +7,9 @@ use serde::{Deserialize, Serialize};
/// Information about trap. /// Information about trap.
#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Clone, Debug, PartialEq, Eq)] #[derive(
RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Clone, Debug, PartialEq, Eq,
)]
#[archive(as = "Self")] #[archive(as = "Self")]
pub struct TrapInformation { pub struct TrapInformation {
/// The offset of the trapping instruction in native code. It is relative to the beginning of the function. /// The offset of the trapping instruction in native code. It is relative to the beginning of the function.

View File

@@ -19,6 +19,7 @@ use serde::{Deserialize, Serialize};
/// [unwind info]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019 /// [unwind info]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub enum CompiledFunctionUnwindInfo { pub enum CompiledFunctionUnwindInfo {
/// Windows UNWIND_INFO. /// Windows UNWIND_INFO.
WindowsX64(Vec<u8>), WindowsX64(Vec<u8>),

View File

@@ -34,6 +34,7 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct PrimaryMap<K, V> pub struct PrimaryMap<K, V>
where where
K: EntityRef, K: EntityRef,

View File

@@ -28,6 +28,7 @@ use serde::{
/// The map does not track if an entry for a key has been inserted or not. Instead it behaves as if /// The map does not track if an entry for a key has been inserted or not. Instead it behaves as if
/// all keys have a default entry from the beginning. /// all keys have a default entry from the beginning.
#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(rkyv::CheckBytes))]
pub struct SecondaryMap<K, V> pub struct SecondaryMap<K, V>
where where
K: EntityRef, K: EntityRef,

View File

@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
/// Features usually have a corresponding [WebAssembly proposal]. /// Features usually have a corresponding [WebAssembly proposal].
/// ///
/// [WebAssembly proposal]: https://github.com/WebAssembly/proposals /// [WebAssembly proposal]: https://github.com/WebAssembly/proposals
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, rkyv::CheckBytes)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive(as = "Self")] #[archive(as = "Self")]

View File

@@ -18,6 +18,7 @@ use serde::{Deserialize, Serialize};
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -49,6 +50,7 @@ entity_impl!(LocalMemoryIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -68,6 +70,7 @@ entity_impl!(LocalGlobalIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -87,6 +90,7 @@ entity_impl!(FunctionIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -106,6 +110,7 @@ entity_impl!(TableIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -125,6 +130,7 @@ entity_impl!(GlobalIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -144,6 +150,7 @@ entity_impl!(MemoryIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -163,6 +170,7 @@ entity_impl!(SignatureIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -182,6 +190,7 @@ entity_impl!(DataIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -201,6 +210,7 @@ entity_impl!(ElemIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -220,9 +230,11 @@ entity_impl!(CustomSectionIndex);
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum ExportIndex { pub enum ExportIndex {
/// Function export. /// Function export.
Function(FunctionIndex), Function(FunctionIndex),
@@ -236,10 +248,21 @@ pub enum ExportIndex {
/// An entity to import. /// An entity to import.
#[derive( #[derive(
Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, RkyvSerialize, RkyvDeserialize, Archive, Clone,
Debug,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
RkyvSerialize,
RkyvDeserialize,
Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum ImportIndex { pub enum ImportIndex {
/// Function import. /// Function import.
Function(FunctionIndex), Function(FunctionIndex),

View File

@@ -1,13 +1,14 @@
use crate::indexes::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex}; use crate::indexes::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex};
use crate::lib::std::boxed::Box; use crate::lib::std::boxed::Box;
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, CheckBytes, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")] #[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// A WebAssembly table initializer. /// A WebAssembly table initializer.
#[derive(Clone, Debug, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Clone, Debug, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive_attr(derive(CheckBytes))]
pub struct TableInitializer { pub struct TableInitializer {
/// The index of a table to initialize. /// The index of a table to initialize.
pub table_index: TableIndex, pub table_index: TableIndex,
@@ -23,6 +24,7 @@ pub struct TableInitializer {
/// should be performed. /// should be performed.
#[derive(Clone, Debug, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Clone, Debug, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive_attr(derive(CheckBytes))]
pub struct DataInitializerLocation { pub struct DataInitializerLocation {
/// The index of the memory to initialize. /// The index of the memory to initialize.
pub memory_index: MemoryIndex, pub memory_index: MemoryIndex,
@@ -49,6 +51,7 @@ pub struct DataInitializer<'data> {
/// holding a reference to it /// holding a reference to it
#[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Debug, Clone, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive_attr(derive(CheckBytes))]
pub struct OwnedDataInitializer { pub struct OwnedDataInitializer {
/// The location where the initialization is to be performed. /// The location where the initialization is to be performed.
pub location: DataInitializerLocation, pub location: DataInitializerLocation,

View File

@@ -18,9 +18,11 @@ use std::fmt;
RkyvSerialize, RkyvSerialize,
RkyvDeserialize, RkyvDeserialize,
Archive, Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u16)]
pub enum LibCall { pub enum LibCall {
/// ceil.f32 /// ceil.f32
CeilF32, CeilF32,

View File

@@ -7,9 +7,21 @@ use std::iter::Sum;
use std::ops::{Add, AddAssign}; use std::ops::{Add, AddAssign};
/// Implementation styles for WebAssembly linear memory. /// Implementation styles for WebAssembly linear memory.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
RkyvSerialize,
RkyvDeserialize,
Archive,
rkyv::CheckBytes,
)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum MemoryStyle { pub enum MemoryStyle {
/// The actual memory can be resized and moved. /// The actual memory can be resized and moved.
Dynamic { Dynamic {

View File

@@ -14,8 +14,8 @@ use crate::{
use indexmap::IndexMap; use indexmap::IndexMap;
use rkyv::{ use rkyv::{
de::SharedDeserializeRegistry, ser::ScratchSpace, ser::Serializer, de::SharedDeserializeRegistry, ser::ScratchSpace, ser::Serializer,
ser::SharedSerializeRegistry, Archive, Archived, Deserialize as RkyvDeserialize, Fallible, ser::SharedSerializeRegistry, Archive, Archived, CheckBytes, Deserialize as RkyvDeserialize,
Serialize as RkyvSerialize, Fallible, Serialize as RkyvSerialize,
}; };
#[cfg(feature = "enable-serde")] #[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -26,6 +26,7 @@ use std::iter::ExactSizeIterator;
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(CheckBytes))]
pub struct ModuleId { pub struct ModuleId {
id: usize, id: usize,
} }
@@ -48,6 +49,7 @@ impl Default for ModuleId {
/// Hash key of an import /// Hash key of an import
#[derive(Debug, Hash, Eq, PartialEq, Clone, Default, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(Debug, Hash, Eq, PartialEq, Clone, Default, RkyvSerialize, RkyvDeserialize, Archive)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive_attr(derive(CheckBytes, PartialEq, Eq, Hash))]
pub struct ImportKey { pub struct ImportKey {
/// Module name /// Module name
pub module: String, pub module: String,
@@ -177,6 +179,7 @@ pub struct ModuleInfo {
/// Mirror version of ModuleInfo that can derive rkyv traits /// Mirror version of ModuleInfo that can derive rkyv traits
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(CheckBytes))]
pub struct ArchivableModuleInfo { pub struct ArchivableModuleInfo {
name: Option<String>, name: Option<String>,
imports: IndexMap<ImportKey, ImportIndex>, imports: IndexMap<ImportKey, ImportIndex>,

View File

@@ -6,9 +6,10 @@ use crate::{
SerializeError, SignatureIndex, TableIndex, TableStyle, SerializeError, SignatureIndex, TableIndex, TableStyle,
}; };
use enumset::EnumSet; use enumset::EnumSet;
use rkyv::check_archived_value;
use rkyv::{ use rkyv::{
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer, archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize, ser::Serializer as RkyvSerializer, Archive, CheckBytes, Deserialize as RkyvDeserialize,
Serialize as RkyvSerialize, Serialize as RkyvSerialize,
}; };
use std::convert::TryInto; use std::convert::TryInto;
@@ -17,6 +18,7 @@ use std::mem;
/// The compilation related data for a serialized modules /// The compilation related data for a serialized modules
#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)] #[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
#[allow(missing_docs)] #[allow(missing_docs)]
#[archive_attr(derive(CheckBytes))]
pub struct SerializableCompilation { pub struct SerializableCompilation {
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>, pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>, pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
@@ -51,6 +53,7 @@ impl SerializableCompilation {
/// Serializable struct that is able to serialize from and to a `ArtifactInfo`. /// Serializable struct that is able to serialize from and to a `ArtifactInfo`.
#[derive(Archive, RkyvDeserialize, RkyvSerialize)] #[derive(Archive, RkyvDeserialize, RkyvSerialize)]
#[allow(missing_docs)] #[allow(missing_docs)]
#[archive_attr(derive(CheckBytes))]
pub struct SerializableModule { pub struct SerializableModule {
/// The main serializable compilation object /// The main serializable compilation object
pub compilation: SerializableCompilation, pub compilation: SerializableCompilation,
@@ -96,6 +99,16 @@ impl SerializableModule {
Self::deserialize_from_archive(archived) Self::deserialize_from_archive(archived)
} }
/// Deserialize a Module from a slice.
/// The slice must have the following format:
/// RKYV serialization (any length) + POS (8 bytes)
///
/// Unlike [`Self::deserialize`], this function will validate the data.
pub fn deserialize_checked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
let archived = Self::archive_from_slice_checked(metadata_slice)?;
Self::deserialize_from_archive(archived)
}
/// # Safety /// # Safety
/// ///
/// This method is unsafe. /// This method is unsafe.
@@ -117,6 +130,25 @@ impl SerializableModule {
)) ))
} }
/// Deserialize an archived module.
///
/// In contrast to [`Self::deserialize`], this method performs validation
/// and is not unsafe.
fn archive_from_slice_checked(
metadata_slice: &[u8],
) -> Result<&ArchivedSerializableModule, DeserializeError> {
if metadata_slice.len() < 8 {
return Err(DeserializeError::Incompatible(
"invalid serialized data".into(),
));
}
let mut pos: [u8; 8] = Default::default();
pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
let pos: u64 = u64::from_le_bytes(pos);
check_archived_value::<Self>(&metadata_slice[..metadata_slice.len() - 8], pos as usize)
.map_err(|err| DeserializeError::CorruptedBinary(err.to_string()))
}
/// Deserialize a compilation module from an archive /// Deserialize a compilation module from an archive
pub fn deserialize_from_archive( pub fn deserialize_from_archive(
archived: &ArchivedSerializableModule, archived: &ArchivedSerializableModule,
@@ -175,7 +207,7 @@ pub struct MetadataHeader {
impl MetadataHeader { impl MetadataHeader {
/// Current ABI version. Increment this any time breaking changes are made /// Current ABI version. Increment this any time breaking changes are made
/// to the format of the serialized data. /// to the format of the serialized data.
const CURRENT_VERSION: u32 = 3; const CURRENT_VERSION: u32 = 4;
/// Magic number to identify wasmer metadata. /// Magic number to identify wasmer metadata.
const MAGIC: [u8; 8] = *b"WASMER\0\0"; const MAGIC: [u8; 8] = *b"WASMER\0\0";

View File

@@ -1,11 +1,15 @@
use bytecheck::CheckBytes;
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")] #[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Implementation styles for WebAssembly tables. /// Implementation styles for WebAssembly tables.
#[derive(Debug, Clone, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive)] #[derive(
Debug, Clone, Hash, PartialEq, Eq, RkyvSerialize, RkyvDeserialize, Archive, CheckBytes,
)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum TableStyle { pub enum TableStyle {
/// Signatures are stored in the table and checked in the caller. /// Signatures are stored in the table and checked in the caller.
CallerChecksSignature, CallerChecksSignature,

View File

@@ -14,7 +14,17 @@ use thiserror::Error;
/// ///
/// All trap instructions have an explicit trap code. /// All trap instructions have an explicit trap code.
#[derive( #[derive(
Clone, Copy, PartialEq, Eq, Debug, Hash, Error, RkyvSerialize, RkyvDeserialize, Archive, Clone,
Copy,
PartialEq,
Eq,
Debug,
Hash,
Error,
RkyvSerialize,
RkyvDeserialize,
Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[repr(u32)] #[repr(u32)]

View File

@@ -6,6 +6,7 @@ use crate::lib::std::string::{String, ToString};
use crate::lib::std::vec::Vec; use crate::lib::std::vec::Vec;
use crate::units::Pages; use crate::units::Pages;
use bytecheck::CheckBytes;
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")] #[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -17,8 +18,9 @@ use serde::{Deserialize, Serialize};
/// A list of all possible value types in WebAssembly. /// A list of all possible value types in WebAssembly.
#[derive(Copy, Debug, Clone, Eq, PartialEq, Hash)] #[derive(Copy, Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes)]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum Type { pub enum Type {
/// Signed 32 bit integer. /// Signed 32 bit integer.
I32, I32,
@@ -58,10 +60,10 @@ impl fmt::Display for Type {
} }
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] /// The WebAssembly V128 type
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, CheckBytes)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
/// The WebAssembly V128 type
#[archive(as = "Self")] #[archive(as = "Self")]
pub struct V128(pub(crate) [u8; 16]); pub struct V128(pub(crate) [u8; 16]);
@@ -240,6 +242,7 @@ impl ExternType {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(CheckBytes))]
pub struct FunctionType { pub struct FunctionType {
/// The parameters of the function /// The parameters of the function
params: Box<[Type]>, params: Box<[Type]>,
@@ -323,10 +326,11 @@ impl From<&Self> for FunctionType {
} }
/// Indicator of whether a global is mutable or not /// Indicator of whether a global is mutable or not
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, CheckBytes)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum Mutability { pub enum Mutability {
/// The global is constant and its value does not change /// The global is constant and its value does not change
Const, Const,
@@ -361,7 +365,7 @@ impl From<Mutability> for bool {
} }
/// WebAssembly global. /// WebAssembly global.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, CheckBytes)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive(as = "Self")] #[archive(as = "Self")]
@@ -408,8 +412,9 @@ impl fmt::Display for GlobalType {
/// Globals are initialized via the `const` operators or by referring to another import. /// Globals are initialized via the `const` operators or by referring to another import.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes)]
#[archive(as = "Self")] #[archive(as = "Self")]
#[repr(u8)]
pub enum GlobalInit { pub enum GlobalInit {
/// An `i32.const`. /// An `i32.const`.
I32Const(i32), I32Const(i32),
@@ -442,6 +447,7 @@ pub enum GlobalInit {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(CheckBytes))]
pub struct TableType { pub struct TableType {
/// The type of data stored in elements of the table. /// The type of data stored in elements of the table.
pub ty: Type, pub ty: Type,
@@ -482,6 +488,7 @@ impl fmt::Display for TableType {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[derive(RkyvSerialize, RkyvDeserialize, Archive)] #[derive(RkyvSerialize, RkyvDeserialize, Archive)]
#[archive_attr(derive(CheckBytes))]
pub struct MemoryType { pub struct MemoryType {
/// The minimum number of pages in the memory. /// The minimum number of pages in the memory.
pub minimum: Pages, pub minimum: Pages,

View File

@@ -21,7 +21,17 @@ pub const WASM_MIN_PAGES: u32 = 0x100;
/// Units of WebAssembly pages (as specified to be 65,536 bytes). /// Units of WebAssembly pages (as specified to be 65,536 bytes).
#[derive( #[derive(
Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RkyvSerialize, RkyvDeserialize, Archive, Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
RkyvSerialize,
RkyvDeserialize,
Archive,
rkyv::CheckBytes,
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[archive(as = "Self")] #[archive(as = "Self")]