concordium_wasm/
parse.rs

1//! This module defines a parser for the Web assembly binary format conforming
2//! to the specification in [wasm-core-1-20191205](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/) but with further
3//! restrictions to ensure suitability for the Concordium blockchain.
4//!
5//! In particular all floating point types and instructions are removed and will
6//! cause a parsing error. The reason for this is that we currently do not
7//! support floating point types to ensure determinism, and to simplify the
8//! validator and further stages we simply remove those instructions at the
9//! parsing stage.
10//!
11//! Parsing is organized into two stages. In the first stage bytes are parsed
12//! into a [`Skeleton`], which is simply a list of sections, the sections
13//! themselves being unparsed. This structure is useful for some operations,
14//! such as pruning and embedding additional metadata into the module.
15//!
16//! In the second stage each section can be parsed into a proper structure.
17use crate::{constants::*, types::*, validate::ValidationConfig};
18use anyhow::{bail, ensure};
19use std::{
20    convert::TryFrom,
21    io::{Cursor, Read, Seek, SeekFrom},
22    rc::Rc,
23};
24
25/// Type alias used in the Wasm specification.
26pub type Byte = u8;
27
28#[derive(Debug)]
29/// A section carved out of a module, but with no further processing.
30/// It can be serialized back by writing the section ID and bytes together with
31/// the length. The lifetime is the lifetime of the original byte array this
32/// section was carved from.
33pub struct UnparsedSection<'a> {
34    pub(crate) section_id: SectionId,
35    pub(crate) bytes:      &'a [u8],
36    /// The size of the section as it appears in the original module.
37    /// This includes the section id, the length header, and the actual
38    /// contents.
39    len:                   u64,
40}
41
42#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Debug)]
43/// All supported section IDs as specified by the Web assembly specification.
44pub enum SectionId {
45    Custom = 0,
46    Type,
47    Import,
48    Function,
49    Table,
50    Memory,
51    Global,
52    Export,
53    Start,
54    Element,
55    Code,
56    Data,
57}
58
59#[derive(Debug)]
60/// Skeleton of a module, which is a list of sections that are minimally
61/// processed.
62pub struct Skeleton<'a> {
63    /// Type section.
64    pub ty:      Option<UnparsedSection<'a>>,
65    /// Import section.
66    pub import:  Option<UnparsedSection<'a>>,
67    /// Function section.
68    pub func:    Option<UnparsedSection<'a>>,
69    /// Table section.
70    pub table:   Option<UnparsedSection<'a>>,
71    /// Memory section.
72    pub memory:  Option<UnparsedSection<'a>>,
73    /// Global section.
74    pub global:  Option<UnparsedSection<'a>>,
75    /// Export section.
76    pub export:  Option<UnparsedSection<'a>>,
77    /// Start section.
78    pub start:   Option<UnparsedSection<'a>>,
79    /// Element section.
80    pub element: Option<UnparsedSection<'a>>,
81    /// Code section.
82    pub code:    Option<UnparsedSection<'a>>,
83    /// Data section.
84    pub data:    Option<UnparsedSection<'a>>,
85    /// A list of custom sections in the order they appeared in the input.
86    pub custom:  Vec<UnparsedSection<'a>>,
87}
88
89impl<'a> Skeleton<'a> {
90    /// Get the total size of all custom sections.
91    pub fn custom_sections_size(&self) -> u64 {
92        // Since this is on a parsed skeleton, it is not possible
93        // to have an overflow, seeing that the sections comes from a real module.
94        self.custom.iter().map(|x| x.len).sum()
95    }
96}
97
98/// Auxiliary type alias used by all the parsing functions.
99pub type ParseResult<A> = anyhow::Result<A>;
100
101/// A trait for parsing data. The lifetime and context are useful when we want
102/// to parse data without copying, which is useful to avoid copying all the
103/// unparsed sections.
104///
105/// The implementors of this trait will generally parse data according to the
106/// format specified by Wasm specification.
107pub trait Parseable<'a, Ctx>: Sized {
108    /// Read a value from the cursor, or signal error.
109    /// This function is responsible for advancing the cursor in-line with the
110    /// data it has read.
111    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self>;
112}
113
114/// An empty context used when we can parse data without an additional context.
115pub(crate) const EMPTY_CTX: () = ();
116
117/// A helper trait for more convenient use. The difference from [`Parseable`] is
118/// that typically the result type is determined by the context, which we take
119/// advantage of to reduce the need for typing annotations which would be needed
120/// by the [`Parseable`] trait.
121///
122/// The reason for that is that this trait defines a new method on the type,
123/// giving us access to all of the convenience features of Rust that come with
124/// it.
125pub trait GetParseable<A, Ctx> {
126    /// Parse an item. Analogous to 'parse', but with the reversed roles for
127    /// types of input and output. In the 'Parseable' trait the trait is defined
128    /// for the type that is to be parsed and the source is fixed, whereas here
129    /// the trait is parameterized by the type to be parsed, and the trait is
130    /// implemented for the source type.
131    fn next(self, ctx: Ctx) -> ParseResult<A>;
132}
133
134/// A generic implementation for a cursor.
135impl<'a, 'b, Ctx, A: Parseable<'a, Ctx>> GetParseable<A, Ctx> for &'b mut Cursor<&'a [u8]> {
136    #[cfg_attr(not(feature = "fuzz-coverage"), inline(always))]
137    fn next(self, ctx: Ctx) -> ParseResult<A> { A::parse(ctx, self) }
138}
139
140/// Another generic implementation, but this time the input is not directly a
141/// readable type. Instead this instance additionally ensures that all of the
142/// input data is used by the parser.
143impl<'a, Ctx, A: Parseable<'a, Ctx>> GetParseable<A, Ctx> for &'a [u8] {
144    #[cfg_attr(not(feature = "fuzz-coverage"), inline(always))]
145    fn next(self, ctx: Ctx) -> ParseResult<A> {
146        let mut cursor = Cursor::new(self);
147        let res = A::parse(ctx, &mut cursor)?;
148        ensure!(cursor.position() == self.len() as u64, "Not all of the contents was consumed.");
149        Ok(res)
150    }
151}
152
153/// Implementation for u16 according to the Wasm specification.
154impl<'a, Ctx> Parseable<'a, Ctx> for u16 {
155    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
156        // 3 is ceil(16 / 7)
157        let res = leb128::read::unsigned(&mut cursor.take(3))?;
158        Ok(u16::try_from(res)?)
159    }
160}
161
162/// Implementation for u32 according to the Wasm specification.
163impl<'a, Ctx> Parseable<'a, Ctx> for u32 {
164    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
165        // 5 is ceil(32 / 7)
166        let res = leb128::read::unsigned(&mut cursor.take(5))?;
167        Ok(u32::try_from(res)?)
168    }
169}
170
171/// Implementation for u64 according to the Wasm specification.
172impl<'a, Ctx> Parseable<'a, Ctx> for u64 {
173    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
174        // 10 is ceil(64 / 7)
175        let res = leb128::read::unsigned(&mut cursor.take(10))?;
176        Ok(res)
177    }
178}
179
180/// Implementation for i32 according to the Wasm specification.
181impl<'a, Ctx> Parseable<'a, Ctx> for i32 {
182    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
183        // 5 is ceil(32 / 7)
184        let res = leb128::read::signed(&mut cursor.take(5))?;
185        Ok(i32::try_from(res)?)
186    }
187}
188
189/// Implementation for i64 according to the Wasm specification.
190impl<'a, Ctx> Parseable<'a, Ctx> for i64 {
191    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
192        let res = leb128::read::signed(&mut cursor.take(10))?;
193        Ok(res)
194    }
195}
196
197/// Parsing of the section ID according to the linked Wasm specification.
198impl<'a, Ctx> Parseable<'a, Ctx> for SectionId {
199    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
200        let mut buf = [0u8; 1];
201        cursor.read_exact(&mut buf)?;
202        use SectionId::*;
203        match buf[0] {
204            0 => Ok(Custom),
205            1 => Ok(Type),
206            2 => Ok(Import),
207            3 => Ok(Function),
208            4 => Ok(Table),
209            5 => Ok(Memory),
210            6 => Ok(Global),
211            7 => Ok(Export),
212            8 => Ok(Start),
213            9 => Ok(Element),
214            10 => Ok(Code),
215            11 => Ok(Data),
216            id => bail!("Unknown section id {}", id),
217        }
218    }
219}
220
221/// Parse a vector of elements according to the Wasm specification.
222/// Specifically this is parsed by reading the length as a u32 and then reading
223/// that many elements.
224impl<'a, Ctx: Copy, A: Parseable<'a, Ctx>> Parseable<'a, Ctx> for Vec<A> {
225    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
226        let len = u32::parse(ctx, cursor)?;
227        let max_initial_capacity =
228            MAX_PREALLOCATED_BYTES / std::cmp::max(1, std::mem::size_of::<A>());
229        let mut out = Vec::with_capacity(std::cmp::min(len as usize, max_initial_capacity));
230        for _ in 0..len {
231            out.push(cursor.next(ctx)?)
232        }
233        Ok(out)
234    }
235}
236
237/// Same as the instance for [`Vec<u8>`](Vec), with the difference that no data
238/// is copied and the result is a reference to the initial byte array.
239impl<'a, Ctx> Parseable<'a, Ctx> for &'a [u8] {
240    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
241        let len = u32::parse(ctx, cursor)?;
242        let pos = cursor.position() as usize;
243        let end = pos + len as usize;
244        ensure!(end <= cursor.get_ref().len(), "Malformed byte array");
245        cursor.seek(SeekFrom::Current(i64::from(len)))?;
246        Ok(&cursor.get_ref()[pos..end])
247    }
248}
249
250/// Special case of a vector where we only expect 0 or 1 elements.
251impl<'a, Ctx: Copy, A: Parseable<'a, Ctx>> Parseable<'a, Ctx> for Option<A> {
252    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
253        match Byte::parse(ctx, cursor)? {
254            0u8 => Ok(None),
255            1u8 => Ok(Some(cursor.next(ctx)?)),
256            tag => bail!("Unsupported option tag: {:#04x}", tag),
257        }
258    }
259}
260
261/// Same as the instance for [`Vec<u8>`](Vec), with the difference that no data
262/// is copied and the result is a reference to the initial byte array.
263impl<'a, Ctx> Parseable<'a, Ctx> for &'a [ValueType] {
264    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
265        let len = u32::parse(ctx, cursor)?;
266        let pos = cursor.position() as usize;
267        let end = pos + len as usize;
268        ensure!(end <= cursor.get_ref().len(), "Malformed byte array");
269        cursor.seek(SeekFrom::Current(i64::from(len)))?;
270        let bytes = &cursor.get_ref()[pos..end];
271        for &byte in bytes {
272            if ValueType::try_from(byte).is_err() {
273                bail!(ParseError::UnsupportedValueType {
274                    byte
275                })
276            }
277        }
278        Ok(unsafe { &*(bytes as *const [u8] as *const [ValueType]) })
279    }
280}
281
282/// Parse a section skeleton, which consists of parsing the section ID
283/// and recording the boundaries of it.
284impl<'a, Ctx: Copy> Parseable<'a, Ctx> for UnparsedSection<'a> {
285    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
286        let start = cursor.position();
287        let section_id = cursor.next(ctx)?;
288        let bytes = cursor.next(ctx)?;
289        let end = cursor.position();
290        let len = end - start;
291        Ok(UnparsedSection {
292            section_id,
293            bytes,
294            len,
295        })
296    }
297}
298
299/// Try to parse the input as a Wasm module in binary format. This function
300/// ensures
301///
302/// - the magic hash at the beginning is correct
303/// - version is correct
304/// - sections are in the correct order
305/// - all input is consumed.
306pub fn parse_skeleton(input: &[u8]) -> ParseResult<Skeleton<'_>> {
307    let cursor = &mut Cursor::new(input);
308    {
309        // check magic hash and version
310        let mut buf = [0u8; 4];
311        cursor.read_exact(&mut buf)?;
312        // ensure magic hash
313        ensure!(buf == MAGIC_HASH, "Unknown magic hash");
314        cursor.read_exact(&mut buf)?;
315        // ensure module version.
316        ensure!(buf == VERSION, "Unsupported version.");
317    }
318    let mut last_section = SectionId::Custom;
319
320    let mut ty = None;
321    let mut import = None;
322    let mut func = None;
323    let mut table = None;
324    let mut memory = None;
325    let mut global = None;
326    let mut export = None;
327    let mut start = None;
328    let mut element = None;
329    let mut code = None;
330    let mut data = None;
331    let mut custom = Vec::new();
332
333    // since read_section advances the cursor by at least one byte this loop will
334    // terminate
335    while cursor.position() < input.len() as u64 {
336        let section = UnparsedSection::parse(EMPTY_CTX, cursor)?;
337        ensure!(
338            section.section_id == SectionId::Custom || section.section_id > last_section,
339            "Section out of place."
340        );
341        if section.section_id != SectionId::Custom {
342            last_section = section.section_id
343        }
344        match section.section_id {
345            SectionId::Custom => custom.push(section),
346            SectionId::Type => ty = Some(section),
347            SectionId::Import => import = Some(section),
348            SectionId::Function => func = Some(section),
349            SectionId::Table => table = Some(section),
350            SectionId::Memory => memory = Some(section),
351            SectionId::Global => global = Some(section),
352            SectionId::Export => export = Some(section),
353            SectionId::Start => start = Some(section),
354            SectionId::Element => element = Some(section),
355            SectionId::Code => code = Some(section),
356            SectionId::Data => data = Some(section),
357        }
358    }
359    // make sure we've read all the input
360    ensure!(cursor.position() as usize == input.len(), "Leftover bytes.");
361    Ok(Skeleton {
362        ty,
363        import,
364        func,
365        table,
366        memory,
367        global,
368        export,
369        start,
370        element,
371        code,
372        data,
373        custom,
374    })
375}
376
377/// Parse a name as specified by the Wasm specification, with our own
378/// restrictions. The restriction we impose is that the name consists solely of
379/// ASCII characters.
380impl<'a, Ctx> Parseable<'a, Ctx> for Name {
381    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
382        let name_bytes: &[u8] = cursor.next(ctx)?;
383        ensure!(name_bytes.len() <= MAX_NAME_SIZE, ParseError::NameTooLong);
384        let name = std::str::from_utf8(name_bytes)?.to_string();
385        ensure!(name.is_ascii(), ParseError::OnlyASCIINames);
386        Ok(Name {
387            name,
388        })
389    }
390}
391
392/// Parse a custom section.
393pub fn parse_custom<'a>(sec: &UnparsedSection<'a>) -> ParseResult<CustomSection<'a>> {
394    let mut cursor = Cursor::new(sec.bytes);
395    let name = cursor.next(EMPTY_CTX)?;
396    let contents = &sec.bytes[cursor.position() as usize..];
397    Ok(CustomSection {
398        name,
399        contents,
400    })
401}
402
403/// Parse a single byte.
404impl<'a, Ctx> Parseable<'a, Ctx> for Byte {
405    fn parse(_ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
406        let mut buf = [0u8; 1];
407        cursor.read_exact(&mut buf)?;
408        Ok(buf[0])
409    }
410}
411
412/// Parse a value type. The Wasm version we support does not have floating point
413/// types, so we disallow them already at the parsing stage.
414impl<'a, Ctx> Parseable<'a, Ctx> for ValueType {
415    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
416        let byte = Byte::parse(ctx, cursor)?;
417        if let Ok(x) = ValueType::try_from(byte) {
418            Ok(x)
419        } else {
420            bail!(ParseError::UnsupportedValueType {
421                byte
422            })
423        }
424    }
425}
426
427/// Parse a limit, and additionally ensure that, if given, the upper bound is
428/// no less than lower bound.
429impl<'a, Ctx: Copy> Parseable<'a, Ctx> for Limits {
430    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
431        match Byte::parse(ctx, cursor)? {
432            0x00 => {
433                let min = cursor.next(ctx)?;
434                Ok(Limits {
435                    min,
436                    max: None,
437                })
438            }
439            0x01 => {
440                let min = cursor.next(ctx)?;
441                let mmax = cursor.next(ctx)?;
442                ensure!(min <= mmax, "Lower limit must be no greater than the upper limit.");
443                Ok(Limits {
444                    min,
445                    max: Some(mmax),
446                })
447            }
448            tag => bail!("Incorrect limits tag {:#04x}.", tag),
449        }
450    }
451}
452
453/// Read a single byte and compare it to the given one, failing if they do not
454/// match.
455fn expect_byte(cursor: &mut Cursor<&[u8]>, byte: Byte) -> ParseResult<()> {
456    let b = Byte::parse(EMPTY_CTX, cursor)?;
457    ensure!(b == byte, "Unexpected byte {:#04x}. Expected {:#04x}", b, byte);
458    Ok(())
459}
460
461/// Parse a function type. Since we do not support multiple return values we
462/// ensure at parse time that there are no more than one return values.
463impl<'a, Ctx: Copy> Parseable<'a, Ctx> for FunctionType {
464    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
465        expect_byte(cursor, 0x60)?;
466        let parameters = cursor.next(ctx)?;
467        let result_vec = Vec::<ValueType>::parse(ctx, cursor)?;
468        ensure!(result_vec.len() <= 1, ParseError::OnlySingleReturn);
469        let result = result_vec.first().copied();
470        Ok(FunctionType {
471            parameters,
472            result,
473        })
474    }
475}
476
477/// Parse a table type. In the version we support there is a single table type,
478/// the funcref, so this only records the resulting table limits.
479/// This instance additionally ensures that the limits are valid, i.e., in range
480/// 2^32. Since the bounds are 32-bit integers, this is true by default.
481impl<'a, Ctx: Copy> Parseable<'a, Ctx> for TableType {
482    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
483        expect_byte(cursor, 0x70)?;
484        let limits = Limits::parse(ctx, cursor)?;
485        ensure!(limits.min <= MAX_INIT_TABLE_SIZE, "Initial table size exceeds allowed limits.");
486        Ok(TableType {
487            limits,
488        })
489    }
490}
491
492/// Memory types are just limits on the size of the memory.
493/// This also ensures that limits are within range 2^16.
494impl<'a, Ctx: Copy> Parseable<'a, Ctx> for MemoryType {
495    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
496        let limits = Limits::parse(ctx, cursor)?;
497        ensure!(
498            limits.min <= MAX_INIT_MEMORY_SIZE,
499            "Initial memory allocation of {} pages exceeds maximum of {}.",
500            limits.min,
501            MAX_INIT_MEMORY_SIZE
502        );
503        match limits.max {
504            Some(x) => ensure!(x <= 1 << 16, "Memory limits must be in range 2^16."),
505            None => ensure!(limits.min <= 1 << 16, "Memory limits must be in range 2^16."),
506        }
507        Ok(MemoryType {
508            limits,
509        })
510    }
511}
512
513impl<'a, Ctx, X: Parseable<'a, Ctx>> Parseable<'a, Ctx> for Rc<X> {
514    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
515        Ok(Rc::new(X::parse(ctx, cursor)?))
516    }
517}
518
519impl<'a, Ctx: Copy> Parseable<'a, Ctx> for TypeSection {
520    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
521        let types = cursor.next(ctx)?;
522        Ok(TypeSection {
523            types,
524        })
525    }
526}
527
528impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ImportDescription {
529    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
530        match Byte::parse(ctx, cursor)? {
531            0x00 => {
532                let type_idx = cursor.next(ctx)?;
533                Ok(ImportDescription::Func {
534                    type_idx,
535                })
536            }
537            tag => bail!(ParseError::UnsupportedImportType {
538                tag
539            }),
540        }
541    }
542}
543
544impl<'a, Ctx: Copy> Parseable<'a, Ctx> for Import {
545    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
546        let mod_name = cursor.next(ctx)?;
547        let item_name = cursor.next(ctx)?;
548        let description = cursor.next(ctx)?;
549        Ok(Import {
550            mod_name,
551            item_name,
552            description,
553        })
554    }
555}
556
557impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ImportSection {
558    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
559        let imports = cursor.next(ctx)?;
560        Ok(ImportSection {
561            imports,
562        })
563    }
564}
565
566impl<'a, Ctx: Copy> Parseable<'a, Ctx> for FunctionSection {
567    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
568        let types = cursor.next(ctx)?;
569        Ok(FunctionSection {
570            types,
571        })
572    }
573}
574
575#[derive(Copy, Clone, Debug)]
576/// Internal (to the library) helper to provide as context
577/// when parsing instructions and sections where we need to distinguish
578/// between the different versions of the Wasm spec we support.
579///
580/// Note that this is analogous to
581/// [`ValidationConfig`](crate::validate::ValidationConfig), but instead of just
582/// listing which things are allowed, it provides additional context needed
583/// during parsing.
584/// Currently this context is just a list of globals.
585pub(crate) struct InstructionValidationContext<'a> {
586    /// If globals are allowed, then this is a parsed global section, otherwise
587    /// it is [`None`].
588    pub(crate) globals_allowed:            Option<&'a GlobalSection>,
589    /// Whether to allow the instructions listed in the sign extension proposal.
590    pub(crate) allow_sign_extension_instr: bool,
591}
592
593/// Attempt to read a constant expression of given type (see section 3.3.7.2).
594/// The `ty` argument specifies the expected type of the expression.
595/// For the version of the standard we use this is always a single value type,
596/// and thus any constant expression will be a single instruction.
597///
598/// Constant expressions appear in three places in the wasm specification we
599/// support.
600///
601/// - As initializers for globals. In that case the format of constant
602///   expressions is more restricted. They are not allowed to refer to globals
603///   defined in the current modules. This prevents circularity, although a more
604///   relaxed condition could be used. The function supports this mode of
605///   constant expressions by using `None` as the last argument.
606/// - As offset expressions in element and data segments. In these contexts the
607///   constant expressions are allowed to refer to `GlobalGet` instructions for
608///   `const` globals of the right type.
609fn read_constant_expr(
610    cursor: &mut Cursor<&'_ [u8]>,
611    ty: ValueType,
612    ctx: InstructionValidationContext,
613) -> ParseResult<GlobalInit> {
614    // In principle it does not matter whether we allow or do not allow sign
615    // extension instructions since they are not constant. However the failure/error
616    // will be slightly different. It is more consistent to parse the instruction as
617    // allowed, and then reject as non-constant, as opposed to not-allow at all.
618    let instr = decode_opcode(ctx.allow_sign_extension_instr, cursor)?;
619    let res = match instr {
620        OpCode::I32Const(n) => {
621            ensure!(ty == ValueType::I32, "Constant instruction of type I64, but I32 expected.");
622            GlobalInit::I32(n)
623        }
624        OpCode::I64Const(n) => {
625            ensure!(ty == ValueType::I64, "Constant instruction of type I32, but I64 expected.");
626            GlobalInit::I64(n)
627        }
628        OpCode::GlobalGet(idx) => match ctx.globals_allowed {
629            None => bail!("GlobalGet not allowed in this constant expression."),
630            Some(globals) => {
631                let global = globals.get(idx).ok_or_else(|| {
632                    anyhow::anyhow!("Reference to non-existent global in constant expression.")
633                })?;
634                ensure!(
635                    global.init.ty() == ty,
636                    "Global in constant expression of incorrect type: {:?} != {:?}",
637                    global.init.ty(),
638                    ty
639                );
640                ensure!(
641                    !global.mutable,
642                    "Only references to constant globals can appear in constant expressions."
643                );
644                global.init
645            }
646        },
647        _ => bail!("Not a constant instruction {:?}.", instr),
648    };
649    // end parsing the expression
650    expect_byte(cursor, END)?;
651    Ok(res)
652}
653
654impl<'a, Ctx: Copy> Parseable<'a, Ctx> for TableSection {
655    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
656        let table_type_vec: Vec<TableType> = cursor.next(ctx)?;
657        ensure!(table_type_vec.len() <= 1, "Only table with index 0 is supported.");
658        Ok(TableSection {
659            table_type: table_type_vec.first().copied(),
660        })
661    }
662}
663
664impl<'a, Ctx: Copy> Parseable<'a, Ctx> for MemorySection {
665    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
666        let memory_types_vec: Vec<MemoryType> = cursor.next(ctx)?;
667        ensure!(memory_types_vec.len() <= 1, "Only memory with index 1 is supported.");
668        Ok(MemorySection {
669            memory_type: memory_types_vec.first().copied(),
670        })
671    }
672}
673
674impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ExportDescription {
675    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
676        match Byte::parse(ctx, cursor)? {
677            0x00 => {
678                let index = FuncIndex::parse(ctx, cursor)?;
679                Ok(ExportDescription::Func {
680                    index,
681                })
682            }
683            0x01 => {
684                let index = TableIndex::parse(ctx, cursor)?;
685                ensure!(index == 0, "Only table with index 0 is supported.");
686                Ok(ExportDescription::Table)
687            }
688            0x02 => {
689                let index = MemIndex::parse(ctx, cursor)?;
690                ensure!(index == 0, "Only memory with index 0 is supported.");
691                Ok(ExportDescription::Memory)
692            }
693            0x03 => {
694                let index = GlobalIndex::parse(ctx, cursor)?;
695                Ok(ExportDescription::Global {
696                    index,
697                })
698            }
699            byte => bail!("Unsupported export tag {:#04x}.", byte),
700        }
701    }
702}
703
704impl<'a, Ctx: Copy> Parseable<'a, Ctx> for Export {
705    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
706        let name: Name = cursor.next(ctx)?;
707        let description = cursor.next(ctx)?;
708
709        if let ExportDescription::Func {
710            ..
711        } = description
712        {
713            ensure!(
714                name.name.len() <= concordium_contracts_common::constants::MAX_FUNC_NAME_SIZE,
715                ParseError::FuncNameTooLong
716            );
717        }
718
719        Ok(Export {
720            name,
721            description,
722        })
723    }
724}
725
726impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ExportSection {
727    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
728        let exports = cursor.next(ctx)?;
729        Ok(ExportSection {
730            exports,
731        })
732    }
733}
734
735impl<'a, Ctx> Parseable<'a, Ctx> for StartSection {
736    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
737        // We deliberately try to parse the index before failing
738        // in order that the error message is more precise.
739        let _idxs: FuncIndex = cursor.next(ctx)?;
740        bail!(ParseError::StartFunctionsNotSupported);
741    }
742}
743
744impl<'a> Parseable<'a, InstructionValidationContext<'_>> for Element {
745    fn parse(
746        ctx: InstructionValidationContext,
747        cursor: &mut Cursor<&'a [u8]>,
748    ) -> ParseResult<Self> {
749        let table_index = TableIndex::parse(ctx, cursor)?;
750        ensure!(table_index == 0, "Only table index 0 is supported.");
751        let offset = read_constant_expr(cursor, ValueType::I32, ctx)?;
752        let inits = cursor.next(ctx)?;
753        if let GlobalInit::I32(offset) = offset {
754            Ok(Element {
755                offset,
756                inits,
757            })
758        } else {
759            bail!("Internal error, parsed a constant of type I32 that is not an I32.");
760        }
761    }
762}
763
764impl<'a> Parseable<'a, InstructionValidationContext<'_>> for ElementSection {
765    fn parse(
766        ctx: InstructionValidationContext<'_>,
767        cursor: &mut Cursor<&'a [u8]>,
768    ) -> ParseResult<Self> {
769        let elements = cursor.next(ctx)?;
770        Ok(ElementSection {
771            elements,
772        })
773    }
774}
775
776impl<'a> Parseable<'a, ValidationConfig> for Global {
777    fn parse(ctx: ValidationConfig, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
778        let ty = cursor.next(ctx)?;
779        let mutable = match Byte::parse(ctx, cursor)? {
780            0x00 => false,
781            0x01 => true,
782            flag => bail!("Unsupported mutability flag {:#04x}", flag),
783        };
784        // Globals initialization expressions cannot refer to other (in-module) globals.
785        let init = read_constant_expr(cursor, ty, InstructionValidationContext {
786            globals_allowed:            None,
787            allow_sign_extension_instr: ctx.allow_sign_extension_instr,
788        })?;
789        Ok(Global {
790            init,
791            mutable,
792        })
793    }
794}
795
796impl<'a> Parseable<'a, ValidationConfig> for GlobalSection {
797    fn parse(ctx: ValidationConfig, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
798        let globals = cursor.next(ctx)?;
799        Ok(GlobalSection {
800            globals,
801        })
802    }
803}
804
805/// The byte used to signal the end of an instruction sequence.
806const END: Byte = 0x0B;
807
808/// The version of Wasm we support only has the empty block type, the I32, and
809/// I64 types. Type indices are not supported.
810impl<'a, Ctx> Parseable<'a, Ctx> for BlockType {
811    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
812        match Byte::parse(ctx, cursor)? {
813            0x40 => Ok(BlockType::EmptyType),
814            0x7F => Ok(BlockType::ValueType(ValueType::I32)),
815            0x7E => Ok(BlockType::ValueType(ValueType::I64)),
816            x => bail!("Unsupported block type {}", x),
817        }
818    }
819}
820
821impl<'a, Ctx: Copy> Parseable<'a, Ctx> for MemArg {
822    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
823        let align = cursor.next(ctx)?;
824        let offset = cursor.next(ctx)?;
825        Ok(MemArg {
826            offset,
827            align,
828        })
829    }
830}
831
832impl<'a, Ctx: Copy> Parseable<'a, Ctx> for Local {
833    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
834        let multiplicity = cursor.next(ctx)?;
835        let ty = cursor.next(ctx)?;
836        Ok(Local {
837            multiplicity,
838            ty,
839        })
840    }
841}
842
843/// The Wasm spec has a typo in the published document, [see](https://github.com/WebAssembly/spec/issues/1522)
844/// The original implementation active in protocols 1-5 on Concordium adhered to
845/// the published version. In protocol 6 and up we disallow referring to locally
846/// defined globals in data and element sections. Since imported globals are
847/// disallowed already in our execution environment, this means we disallow
848/// globals in total.
849impl<'a> Parseable<'a, InstructionValidationContext<'_>> for Data {
850    fn parse(
851        ctx: InstructionValidationContext,
852        cursor: &mut Cursor<&'a [u8]>,
853    ) -> ParseResult<Self> {
854        let index = u32::parse(ctx, cursor)?;
855        ensure!(index == 0, "Only memory index 0 is supported.");
856        let offset = read_constant_expr(cursor, ValueType::I32, ctx)?;
857        let init = cursor.next(ctx)?;
858        if let GlobalInit::I32(offset) = offset {
859            Ok(Data {
860                offset,
861                init,
862            })
863        } else {
864            bail!("Internal error, a constant expression of type I32 is not an I32");
865        }
866    }
867}
868
869impl<'a> Parseable<'a, InstructionValidationContext<'_>> for DataSection {
870    fn parse(
871        ctx: InstructionValidationContext,
872        cursor: &mut Cursor<&'a [u8]>,
873    ) -> ParseResult<Self> {
874        let sections = cursor.next(ctx)?;
875        Ok(DataSection {
876            sections,
877        })
878    }
879}
880
881pub(crate) fn parse_sec_with_default<'a, Ctx, A: Parseable<'a, Ctx> + Default>(
882    ctx: Ctx,
883    sec: &Option<UnparsedSection<'a>>,
884) -> ParseResult<A> {
885    match sec.as_ref() {
886        None => Ok(Default::default()),
887        Some(sec) => sec.bytes.next(ctx),
888    }
889}
890
891#[derive(Debug)]
892/// An error that can occur during parsing of Wasm code.
893pub enum ParseError {
894    UnsupportedInstruction {
895        opcode: Byte,
896    },
897    UnsupportedValueType {
898        byte: Byte,
899    },
900    UnsupportedImportType {
901        tag: Byte,
902    },
903    OnlySingleReturn,
904    OnlyASCIINames,
905    NameTooLong,
906    FuncNameTooLong,
907    StartFunctionsNotSupported,
908}
909
910impl std::fmt::Display for ParseError {
911    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
912        match self {
913            ParseError::UnsupportedInstruction {
914                opcode,
915            } => write!(f, "Unsupported instruction {:#04x}", opcode),
916            ParseError::UnsupportedValueType {
917                byte,
918            } => write!(f, "Unknown value type byte {:#04x}", byte),
919            ParseError::UnsupportedImportType {
920                tag,
921            } => write!(f, "Unsupported import type {:#04x}. Only functions can be imported.", tag),
922            ParseError::OnlySingleReturn => write!(f, "Only single return value is supported."),
923            ParseError::OnlyASCIINames => write!(f, "Only ASCII names are allowed."),
924            ParseError::NameTooLong => write!(f, "Names are limited to {} bytes.", MAX_NAME_SIZE),
925            ParseError::FuncNameTooLong => write!(
926                f,
927                "Names of functions are limited to {} bytes.",
928                concordium_contracts_common::constants::MAX_FUNC_NAME_SIZE
929            ),
930            ParseError::StartFunctionsNotSupported => {
931                write!(f, "Start functions are not supported.")
932            }
933        }
934    }
935}
936
937/// Decode the next opcode directly from the cursor.
938pub(crate) fn decode_opcode(
939    allow_sign_extension_instr: bool,
940    cursor: &mut Cursor<&[u8]>,
941) -> ParseResult<OpCode> {
942    match Byte::parse(EMPTY_CTX, cursor)? {
943        END => Ok(OpCode::End),
944        0x00 => Ok(OpCode::Unreachable),
945        0x01 => Ok(OpCode::Nop),
946        0x02 => {
947            let bt = cursor.next(EMPTY_CTX)?;
948            Ok(OpCode::Block(bt))
949        }
950        0x03 => {
951            let bt = cursor.next(EMPTY_CTX)?;
952            Ok(OpCode::Loop(bt))
953        }
954        0x04 => {
955            let ty = cursor.next(EMPTY_CTX)?;
956            Ok(OpCode::If {
957                ty,
958            })
959        }
960        0x05 => Ok(OpCode::Else),
961        0x0C => {
962            let l = cursor.next(EMPTY_CTX)?;
963            Ok(OpCode::Br(l))
964        }
965        0x0D => {
966            let l = cursor.next(EMPTY_CTX)?;
967            Ok(OpCode::BrIf(l))
968        }
969        0x0E => {
970            let labels = cursor.next(EMPTY_CTX)?;
971            let default = cursor.next(EMPTY_CTX)?;
972            Ok(OpCode::BrTable {
973                labels,
974                default,
975            })
976        }
977        0x0F => Ok(OpCode::Return),
978        0x10 => {
979            let idx = cursor.next(EMPTY_CTX)?;
980            Ok(OpCode::Call(idx))
981        }
982        0x11 => {
983            let ty = cursor.next(EMPTY_CTX)?;
984            expect_byte(cursor, 0x00)?;
985            Ok(OpCode::CallIndirect(ty))
986        }
987        // parametric instructions
988        0x1A => Ok(OpCode::Drop),
989        0x1B => Ok(OpCode::Select),
990        // variable instructions
991        0x20 => {
992            let idx = cursor.next(EMPTY_CTX)?;
993            Ok(OpCode::LocalGet(idx))
994        }
995        0x21 => {
996            let idx = cursor.next(EMPTY_CTX)?;
997            Ok(OpCode::LocalSet(idx))
998        }
999        0x22 => {
1000            let idx = cursor.next(EMPTY_CTX)?;
1001            Ok(OpCode::LocalTee(idx))
1002        }
1003        0x23 => {
1004            let idx = cursor.next(EMPTY_CTX)?;
1005            Ok(OpCode::GlobalGet(idx))
1006        }
1007        0x24 => {
1008            let idx = cursor.next(EMPTY_CTX)?;
1009            Ok(OpCode::GlobalSet(idx))
1010        }
1011        // memory instructions
1012        0x28 => {
1013            let memarg = cursor.next(EMPTY_CTX)?;
1014            Ok(OpCode::I32Load(memarg))
1015        }
1016        0x29 => {
1017            let memarg = cursor.next(EMPTY_CTX)?;
1018            Ok(OpCode::I64Load(memarg))
1019        }
1020        0x2C => {
1021            let memarg = cursor.next(EMPTY_CTX)?;
1022            Ok(OpCode::I32Load8S(memarg))
1023        }
1024        0x2D => {
1025            let memarg = cursor.next(EMPTY_CTX)?;
1026            Ok(OpCode::I32Load8U(memarg))
1027        }
1028        0x2E => {
1029            let memarg = cursor.next(EMPTY_CTX)?;
1030            Ok(OpCode::I32Load16S(memarg))
1031        }
1032        0x2F => {
1033            let memarg = cursor.next(EMPTY_CTX)?;
1034            Ok(OpCode::I32Load16U(memarg))
1035        }
1036        0x30 => {
1037            let memarg = cursor.next(EMPTY_CTX)?;
1038            Ok(OpCode::I64Load8S(memarg))
1039        }
1040        0x31 => {
1041            let memarg = cursor.next(EMPTY_CTX)?;
1042            Ok(OpCode::I64Load8U(memarg))
1043        }
1044        0x32 => {
1045            let memarg = cursor.next(EMPTY_CTX)?;
1046            Ok(OpCode::I64Load16S(memarg))
1047        }
1048        0x33 => {
1049            let memarg = cursor.next(EMPTY_CTX)?;
1050            Ok(OpCode::I64Load16U(memarg))
1051        }
1052        0x34 => {
1053            let memarg = cursor.next(EMPTY_CTX)?;
1054            Ok(OpCode::I64Load32S(memarg))
1055        }
1056        0x35 => {
1057            let memarg = cursor.next(EMPTY_CTX)?;
1058            Ok(OpCode::I64Load32U(memarg))
1059        }
1060        0x36 => {
1061            let memarg = cursor.next(EMPTY_CTX)?;
1062            Ok(OpCode::I32Store(memarg))
1063        }
1064        0x37 => {
1065            let memarg = cursor.next(EMPTY_CTX)?;
1066            Ok(OpCode::I64Store(memarg))
1067        }
1068        0x3A => {
1069            let memarg = cursor.next(EMPTY_CTX)?;
1070            Ok(OpCode::I32Store8(memarg))
1071        }
1072        0x3B => {
1073            let memarg = cursor.next(EMPTY_CTX)?;
1074            Ok(OpCode::I32Store16(memarg))
1075        }
1076        0x3C => {
1077            let memarg = cursor.next(EMPTY_CTX)?;
1078            Ok(OpCode::I64Store8(memarg))
1079        }
1080        0x3D => {
1081            let memarg = cursor.next(EMPTY_CTX)?;
1082            Ok(OpCode::I64Store16(memarg))
1083        }
1084        0x3E => {
1085            let memarg = cursor.next(EMPTY_CTX)?;
1086            Ok(OpCode::I64Store32(memarg))
1087        }
1088        0x3F => {
1089            expect_byte(cursor, 0x00)?;
1090            Ok(OpCode::MemorySize)
1091        }
1092        0x40 => {
1093            expect_byte(cursor, 0x00)?;
1094            Ok(OpCode::MemoryGrow)
1095        }
1096        // constants
1097        0x41 => {
1098            let n = cursor.next(EMPTY_CTX)?;
1099            Ok(OpCode::I32Const(n))
1100        }
1101        0x42 => {
1102            let n = cursor.next(EMPTY_CTX)?;
1103            Ok(OpCode::I64Const(n))
1104        }
1105        // numeric instructions
1106        0x45 => Ok(OpCode::I32Eqz),
1107        0x46 => Ok(OpCode::I32Eq),
1108        0x47 => Ok(OpCode::I32Ne),
1109        0x48 => Ok(OpCode::I32LtS),
1110        0x49 => Ok(OpCode::I32LtU),
1111        0x4A => Ok(OpCode::I32GtS),
1112        0x4B => Ok(OpCode::I32GtU),
1113        0x4C => Ok(OpCode::I32LeS),
1114        0x4D => Ok(OpCode::I32LeU),
1115        0x4E => Ok(OpCode::I32GeS),
1116        0x4F => Ok(OpCode::I32GeU),
1117
1118        0x50 => Ok(OpCode::I64Eqz),
1119        0x51 => Ok(OpCode::I64Eq),
1120        0x52 => Ok(OpCode::I64Ne),
1121        0x53 => Ok(OpCode::I64LtS),
1122        0x54 => Ok(OpCode::I64LtU),
1123        0x55 => Ok(OpCode::I64GtS),
1124        0x56 => Ok(OpCode::I64GtU),
1125        0x57 => Ok(OpCode::I64LeS),
1126        0x58 => Ok(OpCode::I64LeU),
1127        0x59 => Ok(OpCode::I64GeS),
1128        0x5A => Ok(OpCode::I64GeU),
1129
1130        0x67 => Ok(OpCode::I32Clz),
1131        0x68 => Ok(OpCode::I32Ctz),
1132        0x69 => Ok(OpCode::I32Popcnt),
1133        0x6A => Ok(OpCode::I32Add),
1134        0x6B => Ok(OpCode::I32Sub),
1135        0x6C => Ok(OpCode::I32Mul),
1136        0x6D => Ok(OpCode::I32DivS),
1137        0x6E => Ok(OpCode::I32DivU),
1138        0x6F => Ok(OpCode::I32RemS),
1139        0x70 => Ok(OpCode::I32RemU),
1140        0x71 => Ok(OpCode::I32And),
1141        0x72 => Ok(OpCode::I32Or),
1142        0x73 => Ok(OpCode::I32Xor),
1143        0x74 => Ok(OpCode::I32Shl),
1144        0x75 => Ok(OpCode::I32ShrS),
1145        0x76 => Ok(OpCode::I32ShrU),
1146        0x77 => Ok(OpCode::I32Rotl),
1147        0x78 => Ok(OpCode::I32Rotr),
1148
1149        0x79 => Ok(OpCode::I64Clz),
1150        0x7A => Ok(OpCode::I64Ctz),
1151        0x7B => Ok(OpCode::I64Popcnt),
1152        0x7C => Ok(OpCode::I64Add),
1153        0x7D => Ok(OpCode::I64Sub),
1154        0x7E => Ok(OpCode::I64Mul),
1155        0x7F => Ok(OpCode::I64DivS),
1156        0x80 => Ok(OpCode::I64DivU),
1157        0x81 => Ok(OpCode::I64RemS),
1158        0x82 => Ok(OpCode::I64RemU),
1159        0x83 => Ok(OpCode::I64And),
1160        0x84 => Ok(OpCode::I64Or),
1161        0x85 => Ok(OpCode::I64Xor),
1162        0x86 => Ok(OpCode::I64Shl),
1163        0x87 => Ok(OpCode::I64ShrS),
1164        0x88 => Ok(OpCode::I64ShrU),
1165        0x89 => Ok(OpCode::I64Rotl),
1166        0x8A => Ok(OpCode::I64Rotr),
1167
1168        0xA7 => Ok(OpCode::I32WrapI64),
1169
1170        0xAC => Ok(OpCode::I64ExtendI32S),
1171        0xAD => Ok(OpCode::I64ExtendI32U),
1172        0xC0 if allow_sign_extension_instr => Ok(OpCode::I32Extend8S),
1173        0xC1 if allow_sign_extension_instr => Ok(OpCode::I32Extend16S),
1174        0xC2 if allow_sign_extension_instr => Ok(OpCode::I64Extend8S),
1175        0xC3 if allow_sign_extension_instr => Ok(OpCode::I64Extend16S),
1176        0xC4 if allow_sign_extension_instr => Ok(OpCode::I64Extend32S),
1177        byte => bail!(ParseError::UnsupportedInstruction {
1178            opcode: byte,
1179        }),
1180    }
1181}
1182
1183pub(crate) struct OpCodeIterator<'a> {
1184    allow_sign_extension_instr: bool,
1185    state: Cursor<&'a [u8]>,
1186}
1187
1188impl<'a> OpCodeIterator<'a> {
1189    pub fn new(allow_sign_extension_instr: bool, bytes: &'a [u8]) -> Self {
1190        Self {
1191            state: Cursor::new(bytes),
1192            allow_sign_extension_instr,
1193        }
1194    }
1195}
1196
1197impl<'a> Iterator for OpCodeIterator<'a> {
1198    type Item = ParseResult<OpCode>;
1199
1200    fn next(&mut self) -> Option<Self::Item> {
1201        if self.state.position() == self.state.get_ref().len() as u64 {
1202            None
1203        } else {
1204            Some(decode_opcode(self.allow_sign_extension_instr, &mut self.state))
1205        }
1206    }
1207}
1208
1209#[derive(Debug)]
1210/// The body of a function.
1211pub(crate) struct CodeSkeleton<'a> {
1212    /// Declaration of the locals.
1213    pub locals:     Vec<Local>,
1214    /// And uninterpreted instructions.
1215    pub expr_bytes: &'a [u8],
1216}
1217
1218#[derive(Debug, Default)]
1219/// The code section.
1220///
1221/// The [`Default`] instance of this type returns an empty code section.
1222pub(crate) struct CodeSkeletonSection<'a> {
1223    pub impls: Vec<CodeSkeleton<'a>>,
1224}
1225
1226impl<'a, Ctx: Copy> Parseable<'a, Ctx> for CodeSkeleton<'a> {
1227    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
1228        let size: u32 = cursor.next(ctx)?;
1229        let cur_pos = cursor.position();
1230        let locals = cursor.next(ctx)?;
1231        let end_pos = cursor.position();
1232        ensure!(
1233            u64::from(size) >= end_pos - cur_pos,
1234            "We've already read too many bytes, module is malformed."
1235        );
1236        let remaining = u64::from(size) - (end_pos - cur_pos);
1237        ensure!(
1238            ((end_pos + remaining) as usize) <= cursor.get_ref().len(),
1239            "We would need to read beyond the end of the input."
1240        );
1241        let expr_bytes = &cursor.get_ref()[end_pos as usize..(end_pos + remaining) as usize];
1242        cursor.set_position(end_pos + remaining);
1243        Ok(CodeSkeleton {
1244            locals,
1245            expr_bytes,
1246        })
1247    }
1248}
1249
1250impl<'a, Ctx: Copy> Parseable<'a, Ctx> for CodeSkeletonSection<'a> {
1251    fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
1252        let impls = cursor.next(ctx)?;
1253        Ok(CodeSkeletonSection {
1254            impls,
1255        })
1256    }
1257}