@@ -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+
406434impl < ' 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