wasm/validation/modules/exports.rs
1use crate::{
2 core::{
3 decoding::reader::WasmDecoder,
4 structure::modules::{
5 exports::{Export, ExportDesc},
6 globals::Global,
7 indices::{FuncIdx, GlobalIdx, IdxVec, MemIdx, TableIdx, TypeIdx},
8 },
9 },
10 DecodingError, ExternType, MemType, Module, TableType, ValidationError,
11};
12
13impl<'wasm> Export<'wasm> {
14 pub fn decode_and_validate(
15 wasm: &mut WasmDecoder<'wasm>,
16 c_funcs: &IdxVec<FuncIdx, TypeIdx>,
17 c_tables: &IdxVec<TableIdx, TableType>,
18 c_mems: &IdxVec<MemIdx, MemType>,
19 c_globals: &IdxVec<GlobalIdx, Global>,
20 ) -> Result<Self, ValidationError> {
21 let name = wasm.decode_name()?;
22 let desc = ExportDesc::decode_and_validate(wasm, c_funcs, c_tables, c_mems, c_globals)?;
23 Ok(Export { name, desc })
24 }
25}
26
27impl ExportDesc {
28 pub fn decode_and_validate(
29 wasm: &mut WasmDecoder,
30 c_functions: &IdxVec<FuncIdx, TypeIdx>,
31 c_tables: &IdxVec<TableIdx, TableType>,
32 c_mems: &IdxVec<MemIdx, MemType>,
33 c_globals: &IdxVec<GlobalIdx, Global>,
34 ) -> Result<Self, ValidationError> {
35 let desc_id = wasm.decode_u8()?;
36
37 let desc = match desc_id {
38 0x00 => ExportDesc::Func(FuncIdx::decode_and_validate(wasm, c_functions)?),
39 0x01 => ExportDesc::Table(TableIdx::decode_and_validate(wasm, c_tables)?),
40 0x02 => ExportDesc::Mem(MemIdx::decode_and_validate(wasm, c_mems)?),
41 0x03 => ExportDesc::Global(GlobalIdx::decode_and_validate(wasm, c_globals)?),
42 other => return Err(DecodingError::MalformedExportDescDiscriminator(other).into()),
43 };
44 Ok(desc)
45 }
46
47 /// returns the external type of `self` according to typing relation,
48 /// taking `validation_info` as validation context C
49 ///
50 /// # Safety
51 ///
52 /// The caller must ensure that `self` comes from the same
53 /// [`Module`] that is passed as an argument here.
54 #[allow(unused)] // reason = "this function is analogous to ImportDesc::extern_type, however it is not yet clear if it is needed in the future"
55 pub unsafe fn extern_type(&self, validation_info: &Module) -> ExternType {
56 // TODO clean up logic for checking if an exported definition is an
57 // import
58 match self {
59 ExportDesc::Func(func_idx) => {
60 // SAFETY: The caller ensures that the current `ExportDesc`
61 // comes from the same `Module` that is passed into the
62 // current function. Therefore, the function index stored in
63 // `self` must be valid in the given `Module`.
64 let type_idx = unsafe { validation_info.functions.inner().get(*func_idx) };
65 // SAFETY: The type index was just read from the passed
66 // `Module`. Because the `Module` struct
67 // guarantees that all indices contained in it are valid for all
68 // other `IdxVec` vectors in it, this is sound.
69 let func_type = unsafe { validation_info.types.get(*type_idx) };
70 // TODO ugly clone that should disappear when types are directly parsed from bytecode instead of vector copies
71 ExternType::Func(func_type.clone())
72 }
73 ExportDesc::Table(table_idx) => {
74 // SAFETY: The caller ensures that the current `ExportDesc`
75 // comes from the same `Module` that is passed into the
76 // current function. Therefore, the table index stored in `self`
77 // must be valid in the given `Module`.
78 let table_type = unsafe { validation_info.tables.inner().get(*table_idx) };
79
80 ExternType::Table(*table_type)
81 }
82 ExportDesc::Mem(mem_idx) => {
83 // SAFETY: The caller ensures that the current `ExportDesc`
84 // comes from the same `Module` that is passed into the
85 // current function. Therefore, the memory index stored in
86 // `self` must be valid in the given `Module`.
87 let mem_type = unsafe { validation_info.memories.inner().get(*mem_idx) };
88
89 ExternType::Mem(*mem_type)
90 }
91 ExportDesc::Global(global_idx) => {
92 // SAFETY: The caller ensures that the current `ExportDesc`
93 // comes from the same `Module` that is passed into the
94 // current function. Therefore, the global index stored in
95 // `self` must be valid in the given `Module`.
96 let global = unsafe { validation_info.globals.inner().get(*global_idx) };
97
98 ExternType::Global(global.ty)
99 }
100 }
101 }
102}