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