Skip to content

Commit 8c32214

Browse files
feat(validation): store custom sections in ValidationInfo
Signed-off-by: Florian Hartung <florian.hartung@dlr.de>
1 parent d735bd3 commit 8c32214

File tree

1 file changed

+72
-37
lines changed

1 file changed

+72
-37
lines changed

src/validation/mod.rs

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub struct ValidationInfo<'bytecode> {
4949
pub(crate) sidetable: Sidetable,
5050
/// The start function which is automatically executed during instantiation
5151
pub(crate) start: Option<FuncIdx>,
52+
pub(crate) custom_sections: Vec<(&'bytecode str, Span)>,
5253
// pub(crate) exports_length: Exported,
5354
}
5455

@@ -93,45 +94,28 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
9394
let mut header = None;
9495
read_next_header(&mut wasm, &mut header)?;
9596

96-
let skip_section = |wasm: &mut WasmReader, section_header: &mut Option<SectionHeader>| {
97-
handle_section(wasm, section_header, SectionTy::Custom, |wasm, h| {
98-
// customsec ::= section_0(custom)
99-
// custom ::= name byte*
100-
// name ::= b*:vec(byte) => name (if utf8(name) = b*)
101-
// vec(B) ::= n:u32 (x:B)^n => x^n
102-
let _name = wasm.read_name()?;
103-
104-
let remaining_bytes = h
105-
.contents
106-
.from()
107-
.checked_add(h.contents.len())
108-
.and_then(|res| res.checked_sub(wasm.pc))
109-
.ok_or(ValidationError::InvalidCustomSectionLength)?;
110-
111-
// TODO: maybe do something with these remaining bytes?
112-
let mut _bytes = Vec::new();
113-
for _ in 0..remaining_bytes {
114-
_bytes.push(wasm.read_u8()?)
115-
}
116-
Ok(())
117-
})
118-
};
119-
120-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
97+
let mut custom_sections = Vec::new();
98+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
99+
custom_sections.push(custom_section);
100+
}
121101

122102
let types = handle_section(&mut wasm, &mut header, SectionTy::Type, |wasm, _| {
123103
wasm.read_vec(FuncType::read).map(|types| IdxVec::new(types).expect("that index space creation never fails because the length of the types vector is encoded as a 32-bit integer in the bytecode"))
124104
})?
125105
.unwrap_or_default();
126106

127-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
107+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
108+
custom_sections.push(custom_section);
109+
}
128110

129111
let imports = handle_section(&mut wasm, &mut header, SectionTy::Import, |wasm, _| {
130112
wasm.read_vec(|wasm| Import::read_and_validate(wasm, &types))
131113
})?
132114
.unwrap_or_default();
133115

134-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
116+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
117+
custom_sections.push(custom_section);
118+
}
135119

136120
// The `Function` section only covers module-level (or "local") functions.
137121
// Imported functions have their types known in the `import` section. Both
@@ -153,7 +137,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
153137
let functions = ExtendedIdxVec::new(imported_functions.collect(), local_functions)
154138
.map_err(|IdxVecOverflowError| ValidationError::TooManyFunctions)?;
155139

156-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
140+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
141+
custom_sections.push(custom_section);
142+
}
157143

158144
let imported_tables = imports.iter().filter_map(|m| match m.desc {
159145
ImportDesc::Table(table) => Some(table),
@@ -167,7 +153,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
167153
let tables = ExtendedIdxVec::new(imported_tables.collect(), local_tables)
168154
.map_err(|IdxVecOverflowError| ValidationError::TooManyTables)?;
169155

170-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
156+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
157+
custom_sections.push(custom_section);
158+
}
171159

172160
let imported_memories = imports.iter().filter_map(|m| match m.desc {
173161
ImportDesc::Mem(mem) => Some(mem),
@@ -186,7 +174,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
186174
return Err(ValidationError::UnsupportedMultipleMemoriesProposal);
187175
}
188176

189-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
177+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
178+
custom_sections.push(custom_section);
179+
}
190180

191181
let imported_global_types: Vec<GlobalType> = imports
192182
.iter()
@@ -215,7 +205,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
215205
let globals = ExtendedIdxVec::new(imported_globals.collect(), local_globals)
216206
.map_err(|IdxVecOverflowError| ValidationError::TooManyGlobals)?;
217207

218-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
208+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
209+
custom_sections.push(custom_section);
210+
}
219211

220212
let exports = handle_section(&mut wasm, &mut header, SectionTy::Export, |wasm, _| {
221213
wasm.read_vec(|wasm| {
@@ -236,7 +228,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
236228
},
237229
));
238230

239-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
231+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
232+
custom_sections.push(custom_section);
233+
}
240234

241235
let start = handle_section(&mut wasm, &mut header, SectionTy::Start, |wasm, _| {
242236
let func_idx = FuncIdx::read_and_validate(wasm, functions.inner())?;
@@ -267,7 +261,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
267261
}
268262
})?;
269263

270-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
264+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
265+
custom_sections.push(custom_section);
266+
}
271267

272268
let elements = handle_section(&mut wasm, &mut header, SectionTy::Element, |wasm, _| {
273269
ElemType::read_and_validate(
@@ -281,7 +277,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
281277
})?
282278
.unwrap_or_default();
283279

284-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
280+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
281+
custom_sections.push(custom_section);
282+
}
285283

286284
// https://webassembly.github.io/spec/core/binary/modules.html#data-count-section
287285
// As per the official documentation:
@@ -295,7 +293,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
295293
trace!("data count: {dc}");
296294
}
297295

298-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
296+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
297+
custom_sections.push(custom_section);
298+
}
299299

300300
let mut sidetable = Sidetable::new();
301301
let func_blocks_stps = handle_section(&mut wasm, &mut header, SectionTy::Code, |wasm, h| {
@@ -326,7 +326,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
326326
return Err(ValidationError::FunctionAndCodeSectionsHaveDifferentLengths);
327327
}
328328

329-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
329+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
330+
custom_sections.push(custom_section);
331+
}
330332

331333
let data_section = handle_section(&mut wasm, &mut header, SectionTy::Data, |wasm, h| {
332334
// wasm.read_vec(DataSegment::read)
@@ -342,7 +344,9 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
342344
}
343345
}
344346

345-
while (skip_section(&mut wasm, &mut header)?).is_some() {}
347+
while let Some(custom_section) = try_read_custom_section(&mut wasm, &mut header)? {
348+
custom_sections.push(custom_section);
349+
}
346350

347351
// All sections should have been handled
348352
if let Some(header) = header {
@@ -364,6 +368,7 @@ pub fn validate(wasm: &[u8]) -> Result<ValidationInfo<'_>, ValidationError> {
364368
data: data_section,
365369
start,
366370
elements,
371+
custom_sections,
367372
};
368373
validate_no_duplicate_exports(&validation_info)?;
369374

@@ -403,6 +408,29 @@ where
403408
}
404409
}
405410

411+
fn try_read_custom_section<'wasm>(
412+
wasm: &mut WasmReader<'wasm>,
413+
section_header: &mut Option<SectionHeader>,
414+
) -> Result<Option<(&'wasm str, Span)>, ValidationError> {
415+
handle_section(wasm, section_header, SectionTy::Custom, |wasm, h| {
416+
// customsec ::= section_0(custom)
417+
// custom ::= name byte*
418+
// name ::= b*:vec(byte) => name (if utf8(name) = b*)
419+
// vec(B) ::= n:u32 (x:B)^n => x^n
420+
let name = wasm.read_name()?;
421+
422+
let section_end = h.contents.from().checked_add(h.contents.len());
423+
let remaining_bytes = section_end
424+
.and_then(|res| res.checked_sub(wasm.pc))
425+
.ok_or(ValidationError::InvalidCustomSectionLength)?;
426+
let span = Span::new(wasm.pc, remaining_bytes);
427+
428+
wasm.skip(remaining_bytes)?;
429+
430+
Ok((name, span))
431+
})
432+
}
433+
406434
impl<'wasm> ValidationInfo<'wasm> {
407435
/// Returns the imports of this module as an iterator. Each import consist
408436
/// of a module name, a name and an extern type.
@@ -439,4 +467,11 @@ impl<'wasm> ValidationInfo<'wasm> {
439467
(export.name, extern_type)
440468
})
441469
}
470+
471+
/// Returns a list of all custom sections in the bytecode. Every custom
472+
/// section consists of a name and a [`Span`] referring to its contents
473+
/// (excluding the name itself).
474+
pub fn custom_sections(&self) -> &[(&'wasm str, Span)] {
475+
&self.custom_sections
476+
}
442477
}

0 commit comments

Comments
 (0)