wasefire_interpreter/
module.rs1use alloc::vec::Vec;
16use core::cmp::Ordering;
17
18use crate::cursor::*;
19use crate::parser::{SkipData, SkipElem};
20use crate::side_table::*;
21use crate::syntax::*;
22use crate::toctou::*;
23use crate::*;
24
25#[derive(Debug, Clone)]
27pub struct Module<'m> {
28 binary: &'m [u8],
29 types: Vec<FuncType<'m>>,
30 side_table: SideTableView<'m>,
31}
32
33impl<'m> Import<'m> {
34 pub fn type_(&self, module: &Module<'m>) -> ExternType<'m> {
35 self.desc.type_(module)
36 }
37}
38
39impl ImportDesc {
40 pub fn type_<'m>(&self, module: &Module<'m>) -> ExternType<'m> {
41 match *self {
42 ImportDesc::Func(x) => ExternType::Func(module.types[x as usize]),
43 ImportDesc::Table(t) => ExternType::Table(t),
44 ImportDesc::Mem(t) => ExternType::Mem(t),
45 ImportDesc::Global(t) => ExternType::Global(t),
46 }
47 }
48}
49
50impl<'m> Module<'m> {
51 pub fn new(binary: &'m [u8]) -> Result<Self, Error> {
53 crate::valid::verify(binary)?;
54 Ok(unsafe { Self::new_unchecked(binary) })
55 }
56
57 pub unsafe fn new_unchecked(binary: &'m [u8]) -> Self {
63 let mut parser = unsafe { Parser::new(&binary[8 ..]) };
65 let side_table = parser.parse_side_table().into_ok();
66 let mut module = Module { binary: parser.remaining(), types: Vec::new(), side_table };
67 if let Some(mut parser) = module.section(SectionId::Type) {
68 for _ in 0 .. parser.parse_vec().into_ok() {
69 module.types.push(parser.parse_functype().into_ok());
70 }
71 }
72 module
73 }
74
75 pub(crate) fn types(&self) -> &[FuncType<'m>] {
76 &self.types
77 }
78
79 pub(crate) fn imports(&self) -> impl Iterator<Item = Import<'m>> + use<'m> {
80 let (n, mut parser) = match self.section(SectionId::Import) {
81 None => (0, Parser::default()),
82 Some(mut parser) => (parser.parse_vec().into_ok(), parser),
83 };
84 (0 .. n).map(move |_| {
85 let module = parser.parse_name().into_ok();
86 let name = parser.parse_name().into_ok();
87 let desc = parser.parse_importdesc().into_ok();
88 Import { module, name, desc }
89 })
90 }
91}
92
93pub type Parser<'m> = parser::Parser<'m, Use>;
94
95impl<'m> Module<'m> {
96 pub(crate) fn section(&self, expected_id: SectionId) -> Option<Parser<'m>> {
97 let mut parser = unsafe { Parser::new(self.binary) };
98 loop {
99 if parser.is_empty() {
100 return None;
101 }
102 let actual_id = parser.parse_section_id().into_ok();
103 let section = parser.split_section().into_ok();
104 if actual_id == SectionId::Custom {
105 continue;
106 }
107 break match actual_id.order().cmp(&expected_id.order()) {
108 Ordering::Less => continue,
109 Ordering::Equal => Some(section),
110 Ordering::Greater => None,
111 };
112 }
113 }
114
115 pub(crate) fn func_type(&self, x: FuncIdx) -> FuncType<'m> {
116 self.types
117 [self.side_table.metadata::<Use>(x as usize).into_ok().type_idx::<Use>().into_ok()]
118 }
119
120 pub(crate) fn table_type(&self, x: TableIdx) -> TableType {
121 let mut parser = self.section(SectionId::Table).unwrap();
122 for i in 0 .. parser.parse_vec().into_ok() {
123 let t = parser.parse_tabletype().into_ok();
124 if i == x as usize {
125 return t;
126 }
127 }
128 unreachable!()
129 }
130
131 pub(crate) fn mem_type(&self, x: MemIdx) -> MemType {
132 let mut parser = self.section(SectionId::Memory).unwrap();
133 for i in 0 .. parser.parse_vec().into_ok() {
134 let t = parser.parse_memtype().into_ok();
135 if i == x as usize {
136 return t;
137 }
138 }
139 unreachable!()
140 }
141
142 pub(crate) fn global_type(&self, x: GlobalIdx) -> GlobalType {
143 let mut parser = self.section(SectionId::Global).unwrap();
144 for i in 0 .. parser.parse_vec().into_ok() {
145 let t = parser.parse_globaltype().into_ok();
146 parser.skip_to_end(0).into_ok();
147 if i == x as usize {
148 return t;
149 }
150 }
151 unreachable!()
152 }
153
154 pub(crate) fn export(&self, expected_name: &str) -> Option<ExportDesc> {
155 let mut parser = self.section(SectionId::Export).unwrap();
156 for _ in 0 .. parser.parse_vec().into_ok() {
157 let actual_name = parser.parse_name().into_ok();
158 let desc = parser.parse_exportdesc().into_ok();
159 if actual_name == expected_name {
160 return Some(desc);
161 }
162 }
163 None
164 }
165
166 pub(crate) fn elem(&self, x: ElemIdx) -> Parser<'m> {
167 let mut parser = self.section(SectionId::Element).unwrap();
168 for i in 0 .. parser.parse_vec().into_ok() {
169 if i == x as usize {
170 return parser;
171 }
172 parser.parse_elem(&mut SkipElem).into_ok();
173 }
174 unreachable!()
175 }
176
177 pub(crate) fn func(&self, x: FuncIdx) -> (Parser<'m>, Cursor<'m, BranchTableEntry>) {
178 let metadata = self.side_table.metadata::<Use>(x as usize).into_ok();
179 let mut parser = unsafe { Parser::new(self.binary) };
180 unsafe { parser.restore(metadata.parser_state::<Use>().into_ok()) };
181 (parser, Cursor::new(metadata.branch_table::<Use>().into_ok()))
182 }
183
184 pub(crate) fn data(&self, x: DataIdx) -> Parser<'m> {
185 let mut parser = self.section(SectionId::Data).unwrap();
186 for i in 0 .. parser.parse_vec().into_ok() {
187 if i == x as usize {
188 return parser;
189 }
190 parser.parse_data(&mut SkipData).into_ok();
191 }
192 unreachable!()
193 }
194}