Skip to main content

bytecode_lang/
decode.rs

1//! The budgeted binary decoder.
2//!
3//! The decoder treats its input as hostile. It never panics, never recurses,
4//! and never allocates more than the input can justify: every count is
5//! checked against its [`Limits`] entry *and* against the bytes that remain
6//! (each element needs at least a known number of bytes) before anything is
7//! reserved. It checks the format: the header, the section order and
8//! lengths, every tag, UTF-8, `char` validity, canonical instructions, the
9//! constant DAG and its depth. It does not check meaning (whether an index
10//! is in range, whether registers are typed correctly); that is the
11//! verifier's job (`specs/LSB.md` ยง8).
12
13use alloc::vec::Vec;
14use core::fmt;
15
16use crate::call::{ArgKind, CallShape, MAX_ARITY, Param, ParamKind, ParamList};
17use crate::encode::{SECTIONS, section};
18use crate::ids::{ConstId, FuncId, GlobalId, ImportId, Reg, StrId, Target, TypeId};
19use crate::inst::{Inst, InstError};
20use crate::module::{
21    Callee, Const, Export, ExportItem, Function, Global, Handler, Hook, HookBinding, Import,
22    JumpTable, LineRow, LocalVar, Module, Strings,
23};
24use crate::types::{Field, FuncType, Method, StructDef, TypeDef, ValType};
25use crate::{FORMAT_VERSION, MAGIC};
26
27/// The budgets the decoder enforces on untrusted input.
28///
29/// The defaults admit any realistic module (hundreds of megabytes of code)
30/// while bounding the work and memory a hostile file can demand. Lower them
31/// for a sandbox; there is no "unlimited" mode, because the format itself
32/// caps registers, name refs, type refs, and captures at 65,536 per function.
33/// Independently of these numbers, no list is allocated before the input is
34/// known to be long enough to hold it.
35///
36/// # Examples
37///
38/// ```
39/// use bytecode_lang::{decode_with, encode, DecodeErrorKind, Limit, Limits, ModuleBuilder};
40///
41/// let mut m = ModuleBuilder::new();
42/// m.string("a");
43/// m.string("b");
44/// let bytes = encode(&m.finish().unwrap());
45///
46/// let mut limits = Limits::default();
47/// limits.max_strings = 1;
48/// let err = decode_with(&bytes, &limits).unwrap_err();
49/// assert_eq!(err.kind(), &DecodeErrorKind::LimitExceeded(Limit::Strings));
50/// ```
51#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
52#[non_exhaustive]
53pub struct Limits {
54    /// Maximum input size in bytes. Default 256 MiB.
55    pub max_bytes: usize,
56    /// Maximum string-table entries. Default 4,194,304.
57    pub max_strings: usize,
58    /// Maximum type-table entries. Default 1,048,576.
59    pub max_types: usize,
60    /// Maximum constant-pool entries. Default 4,194,304.
61    pub max_consts: usize,
62    /// Maximum nesting depth of aggregate constants (a scalar is depth 1).
63    /// Default 64.
64    pub max_const_depth: u32,
65    /// Maximum functions. Default 1,048,576.
66    pub max_functions: usize,
67    /// Maximum instructions in one function. Default 16,777,216.
68    pub max_insts: usize,
69    /// Maximum instructions in the whole module. Default 33,554,432.
70    pub max_total_insts: usize,
71    /// Maximum length of every other list: imports, globals, exports,
72    /// parameters, methods, constant elements, byte-string constants (in
73    /// bytes), jump-table entries, handlers, line rows, locals. Default
74    /// 16,777,216.
75    pub max_items: usize,
76}
77
78impl Default for Limits {
79    fn default() -> Self {
80        Limits {
81            max_bytes: 256 << 20,
82            max_strings: 1 << 22,
83            max_types: 1 << 20,
84            max_consts: 1 << 22,
85            max_const_depth: 64,
86            max_functions: 1 << 20,
87            max_insts: 1 << 24,
88            max_total_insts: 1 << 25,
89            max_items: 1 << 24,
90        }
91    }
92}
93
94/// Which budget a [`DecodeErrorKind::LimitExceeded`] refers to.
95///
96/// # Examples
97///
98/// ```
99/// use bytecode_lang::Limit;
100///
101/// assert_eq!(Limit::ConstDepth.to_string(), "constant nesting depth");
102/// ```
103#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
104#[non_exhaustive]
105pub enum Limit {
106    /// [`Limits::max_bytes`].
107    Bytes,
108    /// [`Limits::max_strings`].
109    Strings,
110    /// [`Limits::max_types`].
111    Types,
112    /// [`Limits::max_consts`].
113    Consts,
114    /// [`Limits::max_const_depth`].
115    ConstDepth,
116    /// [`Limits::max_functions`].
117    Functions,
118    /// [`Limits::max_insts`].
119    Insts,
120    /// [`Limits::max_total_insts`].
121    TotalInsts,
122    /// [`Limits::max_items`].
123    Items,
124    /// The format's cap of 65,536 entries on the tables a 16-bit operand
125    /// indexes: a function's registers, captures, name refs, type refs, and
126    /// call shapes, and a struct's fields.
127    PerFunction,
128    /// The format's cap of 255 entries on a parameter list or a call shape
129    /// (call windows and argument counts are 8-bit).
130    Arity,
131}
132
133impl fmt::Display for Limit {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        f.write_str(match self {
136            Limit::Bytes => "input size",
137            Limit::Strings => "string count",
138            Limit::Types => "type count",
139            Limit::Consts => "constant count",
140            Limit::ConstDepth => "constant nesting depth",
141            Limit::Functions => "function count",
142            Limit::Insts => "instructions per function",
143            Limit::TotalInsts => "total instructions",
144            Limit::Items => "list length",
145            Limit::PerFunction => "16-bit table size (65,536 entries)",
146            Limit::Arity => "arity (255 parameters or arguments)",
147        })
148    }
149}
150
151/// What is wrong with the input; see [`DecodeError`].
152///
153/// # Examples
154///
155/// ```
156/// use bytecode_lang::{decode, DecodeErrorKind};
157///
158/// assert_eq!(decode(b"LS").unwrap_err().kind(), &DecodeErrorKind::UnexpectedEnd);
159/// assert_eq!(decode(b"MZ\0\0\x01\0\0\0\0\0\0\0").unwrap_err().kind(), &DecodeErrorKind::BadMagic);
160/// ```
161#[derive(Clone, Copy, PartialEq, Eq, Debug)]
162#[non_exhaustive]
163pub enum DecodeErrorKind {
164    /// The input ends before a value it promises.
165    UnexpectedEnd,
166    /// The first four bytes are not `LSB\0`.
167    BadMagic,
168    /// The format version is not one this decoder implements.
169    UnsupportedVersion(u32),
170    /// The header's reserved flags are not zero.
171    ReservedFlags(u32),
172    /// A section id is not the next one in the fixed order.
173    SectionOutOfOrder {
174        /// The id that should come next.
175        expected: u32,
176        /// The id found.
177        found: u32,
178    },
179    /// A section's contents do not fill exactly its declared length.
180    SectionLength(u32),
181    /// Bytes follow the last section.
182    TrailingBytes,
183    /// A budget was exceeded.
184    LimitExceeded(Limit),
185    /// A string is not valid UTF-8.
186    InvalidUtf8,
187    /// A tag byte names nothing (`what` says which kind of tag).
188    InvalidTag {
189        /// The kind of tag: `"value type"`, `"type"`, `"constant"`, ...
190        what: &'static str,
191        /// The byte found.
192        tag: u8,
193    },
194    /// A `char` constant is not a Unicode scalar value.
195    InvalidChar(u32),
196    /// An aggregate constant refers to itself or a later constant.
197    ConstForwardRef {
198        /// The aggregate.
199        index: u32,
200        /// The offending element.
201        child: u32,
202    },
203    /// Hook bindings are not in strictly increasing hook order.
204    HookOrder,
205    /// The debug section's function count differs from the function
206    /// section's.
207    DebugCount {
208        /// Functions in the module.
209        expected: u32,
210        /// Debug entries found.
211        found: u32,
212    },
213    /// An instruction is malformed.
214    Inst(InstError),
215}
216
217impl fmt::Display for DecodeErrorKind {
218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219        match self {
220            DecodeErrorKind::UnexpectedEnd => f.write_str("unexpected end of input"),
221            DecodeErrorKind::BadMagic => f.write_str("not an LSB module (bad magic)"),
222            DecodeErrorKind::UnsupportedVersion(v) => write!(
223                f,
224                "unsupported format version {v} (this decoder reads version {FORMAT_VERSION})"
225            ),
226            DecodeErrorKind::ReservedFlags(v) => write!(f, "reserved header flags set ({v:#x})"),
227            DecodeErrorKind::SectionOutOfOrder { expected, found } => {
228                write!(f, "expected section {expected}, found {found}")
229            }
230            DecodeErrorKind::SectionLength(id) => {
231                write!(f, "section {id} does not match its declared length")
232            }
233            DecodeErrorKind::TrailingBytes => f.write_str("bytes after the last section"),
234            DecodeErrorKind::LimitExceeded(limit) => write!(f, "{limit} limit exceeded"),
235            DecodeErrorKind::InvalidUtf8 => f.write_str("string is not valid UTF-8"),
236            DecodeErrorKind::InvalidTag { what, tag } => write!(f, "invalid {what} tag {tag}"),
237            DecodeErrorKind::InvalidChar(v) => {
238                write!(f, "{v:#x} is not a Unicode scalar value")
239            }
240            DecodeErrorKind::ConstForwardRef { index, child } => write!(
241                f,
242                "constant k{index} refers to k{child}, which is not an earlier constant"
243            ),
244            DecodeErrorKind::HookOrder => {
245                f.write_str("hook bindings are not in strictly increasing order")
246            }
247            DecodeErrorKind::DebugCount { expected, found } => write!(
248                f,
249                "debug section describes {found} functions, the module has {expected}"
250            ),
251            DecodeErrorKind::Inst(e) => write!(f, "{e}"),
252        }
253    }
254}
255
256/// Why bytes are not a module, and where.
257///
258/// # Examples
259///
260/// ```
261/// use bytecode_lang::{decode, DecodeErrorKind};
262///
263/// let err = decode(b"LSB\0\x09\0\0\0\0\0\0\0").unwrap_err();
264/// assert_eq!(err.kind(), &DecodeErrorKind::UnsupportedVersion(9));
265/// assert_eq!(err.offset(), 4);
266/// assert_eq!(
267///     err.to_string(),
268///     "at byte 4: unsupported format version 9 (this decoder reads version 2)",
269/// );
270/// ```
271#[derive(Clone, Copy, PartialEq, Eq, Debug)]
272pub struct DecodeError {
273    offset: usize,
274    kind: DecodeErrorKind,
275}
276
277impl DecodeError {
278    /// The byte offset in the input where the problem was found.
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// use bytecode_lang::decode;
284    ///
285    /// assert_eq!(decode(b"").unwrap_err().offset(), 0);
286    /// ```
287    #[must_use]
288    pub fn offset(&self) -> usize {
289        self.offset
290    }
291
292    /// What the problem is.
293    ///
294    /// # Examples
295    ///
296    /// ```
297    /// use bytecode_lang::{decode, DecodeErrorKind};
298    ///
299    /// assert_eq!(decode(b"").unwrap_err().kind(), &DecodeErrorKind::UnexpectedEnd);
300    /// ```
301    #[must_use]
302    pub fn kind(&self) -> &DecodeErrorKind {
303        &self.kind
304    }
305}
306
307impl fmt::Display for DecodeError {
308    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309        write!(f, "at byte {}: {}", self.offset, self.kind)
310    }
311}
312
313impl core::error::Error for DecodeError {}
314
315type Result<T> = core::result::Result<T, DecodeError>;
316
317/// A cursor over the input with a movable end (the current section's).
318struct Reader<'a> {
319    bytes: &'a [u8],
320    pos: usize,
321    end: usize,
322}
323
324impl<'a> Reader<'a> {
325    fn fail<T>(&self, at: usize, kind: DecodeErrorKind) -> Result<T> {
326        Err(DecodeError { offset: at, kind })
327    }
328
329    fn remaining(&self) -> usize {
330        self.end.saturating_sub(self.pos)
331    }
332
333    fn take(&mut self, n: usize) -> Result<&'a [u8]> {
334        let slice = self
335            .pos
336            .checked_add(n)
337            .filter(|&stop| stop <= self.end)
338            .and_then(|stop| self.bytes.get(self.pos..stop));
339        match slice {
340            Some(s) => {
341                self.pos += n;
342                Ok(s)
343            }
344            None => self.fail(self.pos, DecodeErrorKind::UnexpectedEnd),
345        }
346    }
347
348    fn array<const N: usize>(&mut self) -> Result<[u8; N]> {
349        let at = self.pos;
350        match <[u8; N]>::try_from(self.take(N)?) {
351            Ok(a) => Ok(a),
352            Err(_) => self.fail(at, DecodeErrorKind::UnexpectedEnd),
353        }
354    }
355
356    fn u8(&mut self) -> Result<u8> {
357        Ok(self.array::<1>()?[0])
358    }
359
360    fn u16(&mut self) -> Result<u16> {
361        Ok(u16::from_le_bytes(self.array()?))
362    }
363
364    fn u32(&mut self) -> Result<u32> {
365        Ok(u32::from_le_bytes(self.array()?))
366    }
367
368    fn u64(&mut self) -> Result<u64> {
369        Ok(u64::from_le_bytes(self.array()?))
370    }
371
372    /// Reads a list length and checks it against `limit` and against the
373    /// remaining bytes (each element needs at least `min_size` bytes), so
374    /// the caller may reserve that many elements.
375    fn count(&mut self, limit: usize, which: Limit, min_size: usize) -> Result<usize> {
376        let at = self.pos;
377        let n = self.u32()? as usize;
378        if n > limit {
379            return self.fail(at, DecodeErrorKind::LimitExceeded(which));
380        }
381        if n.saturating_mul(min_size) > self.remaining() {
382            return self.fail(at, DecodeErrorKind::UnexpectedEnd);
383        }
384        Ok(n)
385    }
386
387    fn bool(&mut self, what: &'static str) -> Result<bool> {
388        let at = self.pos;
389        match self.u8()? {
390            0 => Ok(false),
391            1 => Ok(true),
392            tag => self.fail(at, DecodeErrorKind::InvalidTag { what, tag }),
393        }
394    }
395
396    fn opt_u32(&mut self) -> Result<Option<u32>> {
397        if self.bool("option")? {
398            Ok(Some(self.u32()?))
399        } else {
400            Ok(None)
401        }
402    }
403
404    fn val_type(&mut self) -> Result<ValType> {
405        let at = self.pos;
406        let tag = self.u8()?;
407        if let Some(ty) = ValType::from_simple_tag(tag) {
408            return Ok(ty);
409        }
410        if tag == ValType::Ref(TypeId(0)).tag() {
411            return Ok(ValType::Ref(TypeId(self.u32()?)));
412        }
413        self.fail(
414            at,
415            DecodeErrorKind::InvalidTag {
416                what: "value type",
417                tag,
418            },
419        )
420    }
421
422    fn val_types(&mut self, limit: usize, which: Limit) -> Result<Vec<ValType>> {
423        let n = self.count(limit, which, 1)?;
424        let mut out = Vec::with_capacity(n);
425        for _ in 0..n {
426            out.push(self.val_type()?);
427        }
428        Ok(out)
429    }
430}
431
432/// The largest per-function table the format can address.
433const PER_FUNCTION: usize = 1 << 16;
434
435struct Decoder<'a, 'l> {
436    r: Reader<'a>,
437    limits: &'l Limits,
438    total_insts: usize,
439}
440
441impl Decoder<'_, '_> {
442    fn items(&mut self, min_size: usize) -> Result<usize> {
443        self.r.count(self.limits.max_items, Limit::Items, min_size)
444    }
445
446    fn per_function(&mut self, min_size: usize) -> Result<usize> {
447        let (limit, which) = if self.limits.max_items < PER_FUNCTION {
448            (self.limits.max_items, Limit::Items)
449        } else {
450            (PER_FUNCTION, Limit::PerFunction)
451        };
452        self.r.count(limit, which, min_size)
453    }
454
455    fn strings(&mut self) -> Result<Strings> {
456        let n = self.r.count(self.limits.max_strings, Limit::Strings, 4)?;
457        let mut strings = Strings::with_capacity(n, self.r.remaining());
458        for _ in 0..n {
459            let len = self.r.u32()? as usize;
460            let at = self.r.pos;
461            let bytes = self.r.take(len)?;
462            let Ok(s) = core::str::from_utf8(bytes) else {
463                return self.r.fail(at, DecodeErrorKind::InvalidUtf8);
464            };
465            if !strings.push(s) {
466                return self
467                    .r
468                    .fail(at, DecodeErrorKind::LimitExceeded(Limit::Bytes));
469            }
470        }
471        Ok(strings)
472    }
473
474    fn type_def(&mut self) -> Result<TypeDef> {
475        let at = self.r.pos;
476        Ok(match self.r.u8()? {
477            0 => {
478                let params = self.r.val_types(self.limits.max_items, Limit::Items)?;
479                let results = self.r.val_types(self.limits.max_items, Limit::Items)?;
480                TypeDef::Func(FuncType { params, results })
481            }
482            1 => {
483                let name = StrId(self.r.u32()?);
484                let parent = self.r.opt_u32()?.map(TypeId);
485                let n = self.per_function(5)?;
486                let mut fields = Vec::with_capacity(n);
487                for _ in 0..n {
488                    let name = StrId(self.r.u32()?);
489                    let ty = self.r.val_type()?;
490                    fields.push(Field { name, ty });
491                }
492                let n = self.items(8)?;
493                let mut methods = Vec::with_capacity(n);
494                for _ in 0..n {
495                    let name = StrId(self.r.u32()?);
496                    let func = FuncId(self.r.u32()?);
497                    methods.push(Method { name, func });
498                }
499                TypeDef::Struct(StructDef {
500                    name,
501                    parent,
502                    fields,
503                    methods,
504                })
505            }
506            2 => TypeDef::Array(self.r.val_type()?),
507            3 => {
508                let key = self.r.val_type()?;
509                let value = self.r.val_type()?;
510                TypeDef::Map { key, value }
511            }
512            4 => TypeDef::Cell(self.r.val_type()?),
513            5 => {
514                let key = self.r.val_type()?;
515                let value = self.r.val_type()?;
516                TypeDef::Iter { key, value }
517            }
518            6 => TypeDef::Coroutine,
519            tag => {
520                return self
521                    .r
522                    .fail(at, DecodeErrorKind::InvalidTag { what: "type", tag });
523            }
524        })
525    }
526
527    fn types(&mut self) -> Result<Vec<TypeDef>> {
528        // The smallest type (`coroutine`) is its tag alone.
529        let n = self.r.count(self.limits.max_types, Limit::Types, 1)?;
530        let mut types = Vec::with_capacity(n);
531        for _ in 0..n {
532            types.push(self.type_def()?);
533        }
534        Ok(types)
535    }
536
537    fn consts(&mut self) -> Result<Vec<Const>> {
538        let n = self.r.count(self.limits.max_consts, Limit::Consts, 2)?;
539        let mut consts = Vec::with_capacity(n);
540        // depth[i] = nesting depth of constant i; children are earlier, so
541        // one forward pass computes it with no recursion.
542        let mut depth: Vec<u32> = Vec::with_capacity(n);
543        for index in 0..n {
544            let at = self.r.pos;
545            let c = match self.r.u8()? {
546                0 => Const::Bool(self.r.bool("boolean")?),
547                1 => Const::Int(i64::from_le_bytes(self.r.array()?)),
548                2 => Const::UInt(self.r.u64()?),
549                3 => Const::F32(self.r.u32()?),
550                4 => Const::F64(self.r.u64()?),
551                5 => {
552                    let char_at = self.r.pos;
553                    let v = self.r.u32()?;
554                    match char::from_u32(v) {
555                        Some(c) => Const::Char(c),
556                        None => return self.r.fail(char_at, DecodeErrorKind::InvalidChar(v)),
557                    }
558                }
559                6 => Const::Str(StrId(self.r.u32()?)),
560                7 => {
561                    let len = self.items(1)?;
562                    Const::Bytes(self.r.take(len)?.to_vec())
563                }
564                8 => {
565                    let len = self.items(4)?;
566                    let mut items = Vec::with_capacity(len);
567                    for _ in 0..len {
568                        items.push(ConstId(self.r.u32()?));
569                    }
570                    Const::Array(items)
571                }
572                9 => {
573                    let len = self.items(8)?;
574                    let mut entries = Vec::with_capacity(len);
575                    for _ in 0..len {
576                        let k = ConstId(self.r.u32()?);
577                        let v = ConstId(self.r.u32()?);
578                        entries.push((k, v));
579                    }
580                    Const::Map(entries)
581                }
582                tag => {
583                    return self.r.fail(
584                        at,
585                        DecodeErrorKind::InvalidTag {
586                            what: "constant",
587                            tag,
588                        },
589                    );
590                }
591            };
592            let mut d = 1u32;
593            for child in c.children() {
594                match depth.get(child.index()) {
595                    Some(&cd) => d = d.max(cd.saturating_add(1)),
596                    None => {
597                        let index = u32::try_from(index).unwrap_or(u32::MAX);
598                        let kind = DecodeErrorKind::ConstForwardRef {
599                            index,
600                            child: child.0,
601                        };
602                        return self.r.fail(at, kind);
603                    }
604                }
605            }
606            if d > self.limits.max_const_depth {
607                return self
608                    .r
609                    .fail(at, DecodeErrorKind::LimitExceeded(Limit::ConstDepth));
610            }
611            depth.push(d);
612            consts.push(c);
613        }
614        Ok(consts)
615    }
616
617    /// A byte that must be within `0..=max`, else an invalid tag.
618    fn small(&mut self, max: u8, what: &'static str) -> Result<u8> {
619        let at = self.r.pos;
620        let v = self.r.u8()?;
621        if v > max {
622            return self
623                .r
624                .fail(at, DecodeErrorKind::InvalidTag { what, tag: v });
625        }
626        Ok(v)
627    }
628
629    /// `opt<paramlist>` (see the encoder's `param_list`).
630    fn param_list(&mut self) -> Result<Option<ParamList>> {
631        if !self.r.bool("option")? {
632            return Ok(None);
633        }
634        let ignore_extra = self.small(1, "parameter list flags")? == 1;
635        // Kind, flags, and an absent name: three bytes at least.
636        let n = self.r.count(MAX_ARITY, Limit::Arity, 3)?;
637        let mut params = Vec::with_capacity(n);
638        for _ in 0..n {
639            let at = self.r.pos;
640            let code = self.r.u8()?;
641            let Some(kind) = ParamKind::from_code(code) else {
642                return self.r.fail(
643                    at,
644                    DecodeErrorKind::InvalidTag {
645                        what: "parameter kind",
646                        tag: code,
647                    },
648                );
649            };
650            let flags = self.small(3, "parameter flags")?;
651            let name = self.r.opt_u32()?.map(StrId);
652            params.push(Param {
653                name,
654                kind,
655                by_ref: flags & 1 != 0,
656                default: flags & 2 != 0,
657            });
658        }
659        Ok(Some(ParamList {
660            params,
661            ignore_extra,
662        }))
663    }
664
665    /// A function's call shapes (see the encoder's `shapes`).
666    fn shapes(&mut self) -> Result<Vec<CallShape>> {
667        let n = self.per_function(4)?;
668        let mut shapes = Vec::with_capacity(n);
669        for _ in 0..n {
670            let len = self.r.count(MAX_ARITY, Limit::Arity, 1)?;
671            let mut args = Vec::with_capacity(len);
672            for _ in 0..len {
673                let at = self.r.pos;
674                args.push(match self.r.u8()? {
675                    0 => ArgKind::Positional,
676                    1 => ArgKind::Named(StrId(self.r.u32()?)),
677                    2 => ArgKind::Spread,
678                    3 => ArgKind::SpreadNamed,
679                    tag => {
680                        return self.r.fail(
681                            at,
682                            DecodeErrorKind::InvalidTag {
683                                what: "call shape argument",
684                                tag,
685                            },
686                        );
687                    }
688                });
689            }
690            shapes.push(CallShape { args });
691        }
692        Ok(shapes)
693    }
694
695    fn imports(&mut self) -> Result<Vec<Import>> {
696        // Three ids and an absent parameter list.
697        let n = self.items(13)?;
698        let mut imports = Vec::with_capacity(n);
699        for _ in 0..n {
700            let module = StrId(self.r.u32()?);
701            let name = StrId(self.r.u32()?);
702            let sig = TypeId(self.r.u32()?);
703            let params = self.param_list()?;
704            imports.push(Import {
705                module,
706                name,
707                sig,
708                params,
709            });
710        }
711        Ok(imports)
712    }
713
714    fn globals(&mut self) -> Result<Vec<Global>> {
715        let n = self.items(7)?;
716        let mut globals = Vec::with_capacity(n);
717        for _ in 0..n {
718            let name = StrId(self.r.u32()?);
719            let ty = self.r.val_type()?;
720            let mutable = self.r.bool("boolean")?;
721            let init = self.r.opt_u32()?.map(ConstId);
722            globals.push(Global {
723                name,
724                ty,
725                mutable,
726                init,
727            });
728        }
729        Ok(globals)
730    }
731
732    fn function(&mut self) -> Result<Function> {
733        let name = StrId(self.r.u32()?);
734        let sig = TypeId(self.r.u32()?);
735        let params = self.param_list()?;
736        let regs = {
737            let n = self.per_function(1)?;
738            let mut v = Vec::with_capacity(n);
739            for _ in 0..n {
740                v.push(self.r.val_type()?);
741            }
742            v
743        };
744        let captures = {
745            let n = self.per_function(1)?;
746            let mut v = Vec::with_capacity(n);
747            for _ in 0..n {
748                v.push(self.r.val_type()?);
749            }
750            v
751        };
752        let names = {
753            let n = self.per_function(4)?;
754            let mut v = Vec::with_capacity(n);
755            for _ in 0..n {
756                v.push(StrId(self.r.u32()?));
757            }
758            v
759        };
760        let type_refs = {
761            let n = self.per_function(4)?;
762            let mut v = Vec::with_capacity(n);
763            for _ in 0..n {
764                v.push(TypeId(self.r.u32()?));
765            }
766            v
767        };
768        let tables = {
769            let n = self.items(8)?;
770            let mut v = Vec::with_capacity(n);
771            for _ in 0..n {
772                let default = Target(self.r.u32()?);
773                let len = self.items(4)?;
774                let mut targets = Vec::with_capacity(len);
775                for _ in 0..len {
776                    targets.push(Target(self.r.u32()?));
777                }
778                v.push(JumpTable { targets, default });
779            }
780            v
781        };
782        let shapes = self.shapes()?;
783        let handlers = {
784            let n = self.items(14)?;
785            let mut v = Vec::with_capacity(n);
786            for _ in 0..n {
787                let start = self.r.u32()?;
788                let end = self.r.u32()?;
789                let target = Target(self.r.u32()?);
790                let catch = Reg(self.r.u16()?);
791                v.push(Handler {
792                    start,
793                    end,
794                    target,
795                    catch,
796                });
797            }
798            v
799        };
800        let code = {
801            let at = self.r.pos;
802            let n = self.r.count(self.limits.max_insts, Limit::Insts, 8)?;
803            self.total_insts = self.total_insts.saturating_add(n);
804            if self.total_insts > self.limits.max_total_insts {
805                return self
806                    .r
807                    .fail(at, DecodeErrorKind::LimitExceeded(Limit::TotalInsts));
808            }
809            // `count` proved the bytes are there; take them in one slice and
810            // decode word by word with no per-word bounds bookkeeping.
811            let start = self.r.pos;
812            let words = self.r.take(n.saturating_mul(8))?;
813            let mut code = Vec::with_capacity(n);
814            for (i, word) in words.chunks_exact(8).enumerate() {
815                let mut bytes = [0u8; 8];
816                bytes.copy_from_slice(word);
817                match Inst::from_bytes(bytes) {
818                    Ok(inst) => code.push(inst),
819                    Err(e) => return self.r.fail(start + i * 8, DecodeErrorKind::Inst(e)),
820                }
821            }
822            code
823        };
824        Ok(Function {
825            name,
826            sig,
827            params,
828            regs,
829            captures,
830            names,
831            type_refs,
832            tables,
833            shapes,
834            handlers,
835            code,
836            lines: Vec::new(),
837            locals: Vec::new(),
838        })
839    }
840
841    fn functions(&mut self) -> Result<Vec<Function>> {
842        // Name, signature, an absent parameter list, and eight list lengths.
843        let n = self
844            .r
845            .count(self.limits.max_functions, Limit::Functions, 41)?;
846        let mut functions = Vec::with_capacity(n);
847        for _ in 0..n {
848            functions.push(self.function()?);
849        }
850        Ok(functions)
851    }
852
853    fn exports(&mut self) -> Result<Vec<Export>> {
854        let n = self.items(9)?;
855        let mut exports = Vec::with_capacity(n);
856        for _ in 0..n {
857            let name = StrId(self.r.u32()?);
858            let at = self.r.pos;
859            let tag = self.r.u8()?;
860            let index = self.r.u32()?;
861            let item = match tag {
862                0 => ExportItem::Func(FuncId(index)),
863                1 => ExportItem::Global(GlobalId(index)),
864                2 => ExportItem::Type(TypeId(index)),
865                tag => {
866                    return self.r.fail(
867                        at,
868                        DecodeErrorKind::InvalidTag {
869                            what: "export",
870                            tag,
871                        },
872                    );
873                }
874            };
875            exports.push(Export { name, item });
876        }
877        Ok(exports)
878    }
879
880    fn hooks(&mut self) -> Result<Vec<HookBinding>> {
881        let n = self.r.count(Hook::ALL.len(), Limit::Items, 6)?;
882        let mut hooks: Vec<HookBinding> = Vec::with_capacity(n);
883        for _ in 0..n {
884            let at = self.r.pos;
885            let code = self.r.u8()?;
886            let Some(hook) = Hook::from_code(code) else {
887                return self.r.fail(
888                    at,
889                    DecodeErrorKind::InvalidTag {
890                        what: "hook",
891                        tag: code,
892                    },
893                );
894            };
895            if hooks.last().is_some_and(|prev| prev.hook >= hook) {
896                return self.r.fail(at, DecodeErrorKind::HookOrder);
897            }
898            let callee_at = self.r.pos;
899            let tag = self.r.u8()?;
900            let index = self.r.u32()?;
901            let callee = match tag {
902                0 => Callee::Func(FuncId(index)),
903                1 => Callee::Import(ImportId(index)),
904                tag => {
905                    return self.r.fail(
906                        callee_at,
907                        DecodeErrorKind::InvalidTag {
908                            what: "callee",
909                            tag,
910                        },
911                    );
912                }
913            };
914            hooks.push(HookBinding { hook, callee });
915        }
916        Ok(hooks)
917    }
918
919    fn debug(&mut self, functions: &mut [Function]) -> Result<()> {
920        let at = self.r.pos;
921        let n = self.r.u32()?;
922        if n as usize != functions.len() {
923            let expected = u32::try_from(functions.len()).unwrap_or(u32::MAX);
924            return self
925                .r
926                .fail(at, DecodeErrorKind::DebugCount { expected, found: n });
927        }
928        for f in functions {
929            let rows = self.items(16)?;
930            f.lines.reserve_exact(rows);
931            for _ in 0..rows {
932                let pc = self.r.u32()?;
933                let file = StrId(self.r.u32()?);
934                let line = self.r.u32()?;
935                let column = self.r.u32()?;
936                f.lines.push(LineRow {
937                    pc,
938                    file,
939                    line,
940                    column,
941                });
942            }
943            let locals = self.items(14)?;
944            f.locals.reserve_exact(locals);
945            for _ in 0..locals {
946                let reg = Reg(self.r.u16()?);
947                let name = StrId(self.r.u32()?);
948                let start = self.r.u32()?;
949                let end = self.r.u32()?;
950                f.locals.push(LocalVar {
951                    reg,
952                    name,
953                    start,
954                    end,
955                });
956            }
957        }
958        Ok(())
959    }
960
961    /// Enters section `id`: checks its header and narrows the reader to it.
962    /// Returns the end of the enclosing region to restore afterwards.
963    fn open(&mut self, id: u32) -> Result<usize> {
964        let at = self.r.pos;
965        let found = self.r.u32()?;
966        if found != id {
967            return self.r.fail(
968                at,
969                DecodeErrorKind::SectionOutOfOrder {
970                    expected: id,
971                    found,
972                },
973            );
974        }
975        let len = self.r.u32()? as usize;
976        let start = self.r.pos;
977        match start.checked_add(len).filter(|&end| end <= self.r.end) {
978            Some(end) => {
979                let outer = self.r.end;
980                self.r.end = end;
981                Ok(outer)
982            }
983            None => self.r.fail(start, DecodeErrorKind::UnexpectedEnd),
984        }
985    }
986
987    /// Leaves section `id`, which must have been consumed exactly.
988    fn close(&mut self, id: u32, outer: usize) -> Result<()> {
989        if self.r.pos != self.r.end {
990            return self.r.fail(self.r.pos, DecodeErrorKind::SectionLength(id));
991        }
992        self.r.end = outer;
993        Ok(())
994    }
995}
996
997/// Decodes a module; see [`crate::decode_with`].
998pub(crate) fn decode(bytes: &[u8], limits: &Limits) -> Result<Module> {
999    if bytes.len() > limits.max_bytes {
1000        return Err(DecodeError {
1001            offset: 0,
1002            kind: DecodeErrorKind::LimitExceeded(Limit::Bytes),
1003        });
1004    }
1005    let mut d = Decoder {
1006        r: Reader {
1007            bytes,
1008            pos: 0,
1009            end: bytes.len(),
1010        },
1011        limits,
1012        total_insts: 0,
1013    };
1014    let magic: [u8; 4] = d.r.array()?;
1015    if magic != MAGIC {
1016        return d.r.fail(0, DecodeErrorKind::BadMagic);
1017    }
1018    let version = d.r.u32()?;
1019    if version != FORMAT_VERSION {
1020        return d.r.fail(4, DecodeErrorKind::UnsupportedVersion(version));
1021    }
1022    let flags = d.r.u32()?;
1023    if flags != 0 {
1024        return d.r.fail(8, DecodeErrorKind::ReservedFlags(flags));
1025    }
1026
1027    let mut module = Module::default();
1028    for id in (1u32..).take(SECTIONS) {
1029        let outer = d.open(id)?;
1030        match id {
1031            section::STRINGS => module.strings = d.strings()?,
1032            section::TYPES => module.types = d.types()?,
1033            section::CONSTS => module.consts = d.consts()?,
1034            section::IMPORTS => module.imports = d.imports()?,
1035            section::GLOBALS => module.globals = d.globals()?,
1036            section::FUNCTIONS => module.functions = d.functions()?,
1037            section::EXPORTS => module.exports = d.exports()?,
1038            section::HOOKS => module.hooks = d.hooks()?,
1039            section::META => {
1040                module.name = d.r.opt_u32()?.map(StrId);
1041                module.start = d.r.opt_u32()?.map(FuncId);
1042            }
1043            _ => d.debug(&mut module.functions)?,
1044        }
1045        d.close(id, outer)?;
1046    }
1047    if d.r.pos != bytes.len() {
1048        return d.r.fail(d.r.pos, DecodeErrorKind::TrailingBytes);
1049    }
1050    Ok(module)
1051}