Skip to main content

wasm_smith/
core.rs

1//! Generating arbitrary core Wasm modules.
2
3mod code_builder;
4pub(crate) mod encode;
5mod terminate;
6
7use crate::{Config, arbitrary_loop, limited_string, unique_string};
8use arbitrary::{Arbitrary, Result, Unstructured};
9use code_builder::CodeBuilderAllocations;
10use flagset::{FlagSet, flags};
11use std::collections::{HashMap, HashSet};
12use std::fmt;
13use std::mem;
14use std::ops::Range;
15use std::rc::Rc;
16use std::str::{self, FromStr};
17use wasm_encoder::{
18    AbstractHeapType, ArrayType, BlockType, ConstExpr, Encode, ExportKind, FieldType, HeapType,
19    RefType, StorageType, StructType, ValType,
20};
21pub(crate) use wasm_encoder::{GlobalType, MemoryType, TableType};
22
23// NB: these constants are used to control the rate at which various events
24// occur. For more information see where these constants are used. Their values
25// are somewhat random in the sense that they're not scientifically determined
26// or anything like that, I just threw a bunch of random data at wasm-smith and
27// measured various rates of ooms/traps/etc and adjusted these so abnormal
28// events were ~1% of the time.
29const CHANCE_OFFSET_INBOUNDS: usize = 10; // bigger = less traps
30const CHANCE_SEGMENT_ON_EMPTY: usize = 10; // bigger = less traps
31const PCT_INBOUNDS: f64 = 0.995; // bigger = less traps
32
33type Instruction = wasm_encoder::Instruction<'static>;
34
35/// A pseudo-random WebAssembly module.
36///
37/// Construct instances of this type (with default configuration) with [the
38/// `Arbitrary`
39/// trait](https://docs.rs/arbitrary/*/arbitrary/trait.Arbitrary.html).
40///
41/// ## Configuring Generated Modules
42///
43/// To configure the shape of generated module, create a
44/// [`Config`][crate::Config] and then call [`Module::new`][crate::Module::new]
45/// with it.
46pub struct Module {
47    config: Config,
48    duplicate_imports_behavior: DuplicateImportsBehavior,
49    valtypes: Vec<ValType>,
50
51    /// All types locally defined in this module (available in the type index
52    /// space).
53    types: Vec<SubType>,
54
55    /// Non-overlapping ranges within `types` that belong to the same rec
56    /// group. All of `types` is covered by these ranges. When GC is not
57    /// enabled, these are all single-element ranges.
58    rec_groups: Vec<Range<usize>>,
59
60    /// A map from a super type to all of its sub types.
61    super_to_sub_types: HashMap<u32, Vec<u32>>,
62
63    /// Indices within `types` that are not final types.
64    can_subtype: Vec<u32>,
65
66    /// Whether we should encode a types section, even if `self.types` is empty.
67    should_encode_types: bool,
68
69    /// Whether we should propagate sharedness to types generated inside
70    /// `propagate_shared`.
71    must_share: bool,
72
73    /// All of this module's imports. These don't have their own index space,
74    /// but instead introduce entries to each imported entity's associated index
75    /// space.
76    imports: Vec<Imports>,
77
78    /// Whether we should encode an imports section, even if `self.imports` is
79    /// empty.
80    should_encode_imports: bool,
81
82    /// Indices within `types` that are array types.
83    array_types: Vec<u32>,
84
85    /// Indices within `types` that are function types.
86    func_types: Vec<u32>,
87
88    /// Indices within `types that are struct types.
89    struct_types: Vec<u32>,
90
91    /// Number of imported items into this module.
92    num_imports: usize,
93
94    /// The number of tags defined in this module (not imported or
95    /// aliased).
96    num_defined_tags: usize,
97
98    /// The number of functions defined in this module (not imported or
99    /// aliased).
100    num_defined_funcs: usize,
101
102    /// Initialization expressions for all defined tables in this module.
103    defined_tables: Vec<Option<ConstExpr>>,
104
105    /// The number of memories defined in this module (not imported or
106    /// aliased).
107    num_defined_memories: usize,
108
109    /// The indexes and initialization expressions of globals defined in this
110    /// module.
111    defined_globals: Vec<(u32, ConstExpr)>,
112
113    /// All tags available to this module, sorted by their index. The list
114    /// entry is the type of each tag.
115    tags: Vec<TagType>,
116
117    /// All functions available to this module, sorted by their index. The list
118    /// entry points to the index in this module where the function type is
119    /// defined (if available) and provides the type of the function.
120    funcs: Vec<(u32, Rc<FuncType>)>,
121
122    /// All tables available to this module, sorted by their index. The list
123    /// entry is the type of each table.
124    tables: Vec<TableType>,
125
126    /// All globals available to this module, sorted by their index. The list
127    /// entry is the type of each global.
128    globals: Vec<GlobalType>,
129
130    /// All memories available to this module, sorted by their index. The list
131    /// entry is the type of each memory.
132    memories: Vec<MemoryType>,
133
134    exports: Vec<(String, ExportKind, u32)>,
135    start: Option<u32>,
136    elems: Vec<ElementSegment>,
137    code: Vec<Code>,
138    data: Vec<DataSegment>,
139
140    /// The predicted size of the effective type of this module, based on this
141    /// module's size of the types of imports/exports.
142    type_size: u32,
143
144    /// Names currently exported from this module.
145    export_names: HashSet<String>,
146
147    /// What the maximum type index that can be referenced is.
148    max_type_limit: MaxTypeLimit,
149
150    /// Some known-interesting values, such as powers of two, values just before
151    /// or just after a memory size, etc...
152    interesting_values32: Vec<u32>,
153    interesting_values64: Vec<u64>,
154}
155
156impl<'a> Arbitrary<'a> for Module {
157    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
158        Module::new(Config::default(), u)
159    }
160}
161
162impl fmt::Debug for Module {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        f.debug_struct("Module")
165            .field("config", &self.config)
166            .field(&"...", &"...")
167            .finish()
168    }
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub(crate) enum DuplicateImportsBehavior {
173    Allowed,
174    #[cfg_attr(
175        not(feature = "component-model"),
176        expect(
177            dead_code,
178            reason = "Core WebAssembly permits duplicate import module/name pairs"
179        )
180    )]
181    Disallowed,
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
185enum AllowEmptyRecGroup {
186    Yes,
187    No,
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
191enum MaxTypeLimit {
192    ModuleTypes,
193    Num(u32),
194}
195
196impl Module {
197    /// Returns a reference to the internal configuration.
198    pub fn config(&self) -> &Config {
199        &self.config
200    }
201
202    /// Creates a new `Module` with the specified `config` for
203    /// configuration and `Unstructured` for the DNA of this module.
204    pub fn new(config: Config, u: &mut Unstructured<'_>) -> Result<Self> {
205        Self::new_internal(config, u, DuplicateImportsBehavior::Allowed)
206    }
207
208    pub(crate) fn new_internal(
209        config: Config,
210        u: &mut Unstructured<'_>,
211        duplicate_imports_behavior: DuplicateImportsBehavior,
212    ) -> Result<Self> {
213        let mut module = Module::empty(config, duplicate_imports_behavior);
214        module.build(u)?;
215        Ok(module)
216    }
217
218    fn empty(mut config: Config, duplicate_imports_behavior: DuplicateImportsBehavior) -> Self {
219        config.sanitize();
220        Module {
221            config,
222            duplicate_imports_behavior,
223            valtypes: Vec::new(),
224            types: Vec::new(),
225            rec_groups: Vec::new(),
226            can_subtype: Vec::new(),
227            super_to_sub_types: HashMap::new(),
228            should_encode_types: false,
229            imports: Vec::new(),
230            should_encode_imports: false,
231            array_types: Vec::new(),
232            func_types: Vec::new(),
233            struct_types: Vec::new(),
234            num_imports: 0,
235            num_defined_tags: 0,
236            num_defined_funcs: 0,
237            defined_tables: Vec::new(),
238            num_defined_memories: 0,
239            defined_globals: Vec::new(),
240            tags: Vec::new(),
241            funcs: Vec::new(),
242            tables: Vec::new(),
243            globals: Vec::new(),
244            memories: Vec::new(),
245            exports: Vec::new(),
246            start: None,
247            elems: Vec::new(),
248            code: Vec::new(),
249            data: Vec::new(),
250            type_size: 0,
251            export_names: HashSet::new(),
252            max_type_limit: MaxTypeLimit::ModuleTypes,
253            interesting_values32: Vec::new(),
254            interesting_values64: Vec::new(),
255            must_share: false,
256        }
257    }
258}
259
260#[derive(Clone, Debug, PartialEq, Eq, Hash)]
261pub(crate) struct SubType {
262    pub(crate) is_final: bool,
263    pub(crate) supertype: Option<u32>,
264    pub(crate) composite_type: CompositeType,
265    /// How "deep" this subtype's supertype hierarchy is. The base case is 1 and
266    /// if `supertype` is present it's `1 + supertype.depth`.
267    depth: u32,
268}
269
270impl SubType {
271    fn unwrap_struct(&self) -> &StructType {
272        self.composite_type.unwrap_struct()
273    }
274
275    fn unwrap_func(&self) -> &Rc<FuncType> {
276        self.composite_type.unwrap_func()
277    }
278
279    fn unwrap_array(&self) -> &ArrayType {
280        self.composite_type.unwrap_array()
281    }
282}
283
284#[derive(Clone, Debug, PartialEq, Eq, Hash)]
285pub(crate) struct CompositeType {
286    pub inner: CompositeInnerType,
287    pub shared: bool,
288    pub descriptor: Option<u32>,
289    pub describes: Option<u32>,
290}
291
292impl CompositeType {
293    #[cfg(any(feature = "component-model", feature = "wasmparser"))]
294    pub(crate) fn new_func(func: Rc<FuncType>, shared: bool) -> Self {
295        Self {
296            inner: CompositeInnerType::Func(func),
297            shared,
298            descriptor: None,
299            describes: None,
300        }
301    }
302
303    fn unwrap_func(&self) -> &Rc<FuncType> {
304        match &self.inner {
305            CompositeInnerType::Func(f) => f,
306            _ => panic!("not a func"),
307        }
308    }
309
310    fn unwrap_array(&self) -> &ArrayType {
311        match &self.inner {
312            CompositeInnerType::Array(a) => a,
313            _ => panic!("not an array"),
314        }
315    }
316
317    fn unwrap_struct(&self) -> &StructType {
318        match &self.inner {
319            CompositeInnerType::Struct(s) => s,
320            _ => panic!("not a struct"),
321        }
322    }
323}
324
325impl From<&CompositeType> for wasm_encoder::CompositeType {
326    fn from(ty: &CompositeType) -> Self {
327        let inner = match &ty.inner {
328            CompositeInnerType::Array(a) => wasm_encoder::CompositeInnerType::Array(*a),
329            CompositeInnerType::Func(f) => wasm_encoder::CompositeInnerType::Func(
330                wasm_encoder::FuncType::new(f.params.iter().cloned(), f.results.iter().cloned()),
331            ),
332            CompositeInnerType::Struct(s) => wasm_encoder::CompositeInnerType::Struct(s.clone()),
333        };
334        wasm_encoder::CompositeType {
335            shared: ty.shared,
336            inner,
337            descriptor: ty.descriptor,
338            describes: ty.describes,
339        }
340    }
341}
342
343#[derive(Clone, Debug, PartialEq, Eq, Hash)]
344pub(crate) enum CompositeInnerType {
345    Array(ArrayType),
346    Func(Rc<FuncType>),
347    Struct(StructType),
348}
349
350/// A function signature.
351#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
352pub(crate) struct FuncType {
353    /// Types of the parameter values.
354    pub(crate) params: Vec<ValType>,
355    /// Types of the result values.
356    pub(crate) results: Vec<ValType>,
357}
358
359/// An import of an entity provided externally or by a component.
360#[derive(Clone, Debug, PartialEq, Eq, Hash)]
361pub(crate) struct Import {
362    /// The name of the module providing this entity.
363    pub(crate) module: String,
364    /// The name of the entity.
365    pub(crate) name: String,
366    /// The type of this entity.
367    pub(crate) entity_type: EntityType,
368}
369
370#[derive(Clone, Debug, PartialEq, Eq, Hash)]
371pub(crate) enum Imports {
372    Single(Import),
373    Compact1 {
374        module: String,
375        items: Vec<Import>,
376    },
377    Compact2 {
378        module: String,
379        entity_type: EntityType,
380        names: Vec<String>,
381    },
382}
383
384#[derive(Arbitrary)]
385enum ImportsKind {
386    Single,
387    Compact1,
388    Compact2,
389}
390
391/// Type of an entity.
392#[derive(Clone, Debug, PartialEq, Eq, Hash)]
393pub(crate) enum EntityType {
394    /// A global entity.
395    Global(GlobalType),
396    /// A table entity.
397    Table(TableType),
398    /// A memory entity.
399    Memory(MemoryType),
400    /// A tag entity.
401    Tag(TagType),
402    /// A function entity.
403    Func(u32, Rc<FuncType>),
404}
405
406/// Type of a tag.
407#[derive(Clone, Debug, PartialEq, Eq, Hash)]
408pub(crate) struct TagType {
409    /// Index of the function type.
410    func_type_idx: u32,
411    /// Type of the function.
412    func_type: Rc<FuncType>,
413}
414
415#[derive(Debug)]
416struct ElementSegment {
417    kind: ElementKind,
418    ty: RefType,
419    items: Elements,
420}
421
422#[derive(Debug)]
423enum ElementKind {
424    Passive,
425    Declared,
426    Active {
427        table: Option<u32>, // None == table 0 implicitly
428        offset: Offset,
429    },
430}
431
432#[derive(Debug)]
433enum Elements {
434    Functions(Vec<u32>),
435    Expressions(Vec<ConstExpr>),
436}
437
438#[derive(Debug)]
439struct Code {
440    locals: Vec<ValType>,
441    instructions: Instructions,
442}
443
444#[derive(Debug)]
445enum Instructions {
446    Generated(Vec<Instruction>),
447    Arbitrary(Vec<u8>),
448}
449
450#[derive(Debug)]
451struct DataSegment {
452    kind: DataSegmentKind,
453    init: Vec<u8>,
454}
455
456#[derive(Debug)]
457enum DataSegmentKind {
458    Passive,
459    Active { memory_index: u32, offset: Offset },
460}
461
462#[derive(Debug)]
463pub(crate) enum Offset {
464    Const32(i32),
465    Const64(i64),
466    Global(u32),
467}
468
469impl Module {
470    fn build(&mut self, u: &mut Unstructured) -> Result<()> {
471        self.valtypes = configured_valtypes(&self.config);
472
473        let mut generate_arbitrary_imports = true;
474        let mut generate_arbitrary_exports = true;
475        if self.imports_exports_from_module_shape(u)? {
476            generate_arbitrary_imports = false;
477            generate_arbitrary_exports = false;
478        }
479        // We attempt to figure out our available imports *before* creating the types section here,
480        // because the types for the imports are already well-known (specified by the user) and we
481        // must have those populated for all function/etc. imports, no matter what.
482        //
483        // This can affect the available capacity for types and such.
484        //
485        // Conversely, `arbitrary_imports` must follow `arbitrary_types`,
486        // since it uses the generated function and tag types.
487        if self.arbitrary_imports_from_available(u)? {
488            generate_arbitrary_imports = false;
489        }
490        self.arbitrary_types(u)?;
491        if generate_arbitrary_imports {
492            self.arbitrary_imports(u)?;
493        }
494
495        self.should_encode_imports = !self.imports.is_empty() || u.arbitrary()?;
496
497        self.arbitrary_tags(u)?;
498        self.arbitrary_funcs(u)?;
499        self.arbitrary_tables(u)?;
500        self.arbitrary_memories(u)?;
501        self.arbitrary_globals(u)?;
502        if self.required_exports(u)? {
503            generate_arbitrary_exports = false;
504        }
505        if generate_arbitrary_exports {
506            self.arbitrary_exports(u)?;
507        }
508        self.should_encode_types = !self.types.is_empty() || u.arbitrary()?;
509        self.arbitrary_start(u)?;
510        self.arbitrary_elems(u)?;
511        self.arbitrary_data(u)?;
512        self.arbitrary_code(u)?;
513        Ok(())
514    }
515
516    #[inline]
517    fn val_type_is_sub_type(&self, a: ValType, b: ValType) -> bool {
518        match (a, b) {
519            (a, b) if a == b => true,
520            (ValType::Ref(a), ValType::Ref(b)) => self.ref_type_is_sub_type(a, b),
521            _ => false,
522        }
523    }
524
525    /// Is `a` a subtype of `b`?
526    fn ref_type_is_sub_type(&self, a: RefType, b: RefType) -> bool {
527        if a == b {
528            return true;
529        }
530
531        if a.nullable && !b.nullable {
532            return false;
533        }
534
535        self.heap_type_is_sub_type(a.heap_type, b.heap_type)
536    }
537
538    fn heap_type_is_sub_type(&self, a: HeapType, b: HeapType) -> bool {
539        use AbstractHeapType::*;
540        use CompositeInnerType as CT;
541        use HeapType as HT;
542        match (a, b) {
543            (a, b) if a == b => true,
544
545            (
546                HT::Abstract {
547                    shared: a_shared,
548                    ty: a_ty,
549                },
550                HT::Abstract {
551                    shared: b_shared,
552                    ty: b_ty,
553                },
554            ) => {
555                a_shared == b_shared
556                    && match (a_ty, b_ty) {
557                        (Eq | I31 | Struct | Array | None, Any) => true,
558                        (I31 | Struct | Array | None, Eq) => true,
559                        (NoExtern, Extern) => true,
560                        (NoFunc, Func) => true,
561                        (None, I31 | Array | Struct) => true,
562                        (NoExn, Exn) => true,
563                        _ => false,
564                    }
565            }
566
567            (HT::Concrete(a), HT::Abstract { shared, ty })
568            | (HT::Exact(a), HT::Abstract { shared, ty }) => {
569                let a_ty = &self.ty(a).composite_type;
570                if a_ty.shared != shared {
571                    return false;
572                }
573                match ty {
574                    Eq | Any => matches!(a_ty.inner, CT::Array(_) | CT::Struct(_)),
575                    Struct => matches!(a_ty.inner, CT::Struct(_)),
576                    Array => matches!(a_ty.inner, CT::Array(_)),
577                    Func => matches!(a_ty.inner, CT::Func(_)),
578                    _ => false,
579                }
580            }
581
582            (HT::Abstract { shared, ty }, HT::Concrete(b))
583            | (HT::Abstract { shared, ty }, HT::Exact(b)) => {
584                let b_ty = &self.ty(b).composite_type;
585                if shared != b_ty.shared {
586                    return false;
587                }
588                match ty {
589                    None => matches!(b_ty.inner, CT::Array(_) | CT::Struct(_)),
590                    NoFunc => matches!(b_ty.inner, CT::Func(_)),
591                    _ => false,
592                }
593            }
594
595            (HT::Concrete(mut a), HT::Concrete(b)) | (HT::Exact(mut a), HT::Concrete(b)) => loop {
596                if a == b {
597                    return true;
598                }
599                if let Some(supertype) = self.ty(a).supertype {
600                    a = supertype;
601                } else {
602                    return false;
603                }
604            },
605
606            (HT::Concrete(a), HT::Exact(b)) | (HT::Exact(a), HT::Exact(b)) => {
607                return a == b;
608            }
609        }
610    }
611
612    fn arbitrary_types(&mut self, u: &mut Unstructured) -> Result<()> {
613        assert!(self.config.min_types <= self.config.max_types);
614        while self.types.len() < self.config.min_types {
615            self.arbitrary_rec_group(u, AllowEmptyRecGroup::No)?;
616        }
617        while self.types.len() < self.config.max_types {
618            let keep_going = u.arbitrary().unwrap_or(false);
619            if !keep_going {
620                break;
621            }
622            self.arbitrary_rec_group(u, AllowEmptyRecGroup::Yes)?;
623        }
624        Ok(())
625    }
626
627    fn add_type(&mut self, ty: SubType) -> u32 {
628        let index = u32::try_from(self.types.len()).unwrap();
629
630        if let Some(supertype) = ty.supertype {
631            assert_eq!(self.is_shared_type(supertype), ty.composite_type.shared);
632            self.super_to_sub_types
633                .entry(supertype)
634                .or_default()
635                .push(index);
636        }
637
638        let list = match &ty.composite_type.inner {
639            CompositeInnerType::Array(_) => &mut self.array_types,
640            CompositeInnerType::Func(_) => &mut self.func_types,
641            CompositeInnerType::Struct(_) => &mut self.struct_types,
642        };
643        list.push(index);
644
645        // Calculate the recursive depth of this type, and if it's beneath a
646        // threshold then allow future types to subtype this one. Otherwise this
647        // can no longer be subtyped so despite this not being final don't add
648        // it to the `can_subtype` list.
649        //
650        // Note that this limit is intentinally a bit less than the wasm-defined
651        // maximum of 63.
652        const MAX_SUBTYPING_DEPTH: u32 = 60;
653        if !ty.is_final && ty.depth < MAX_SUBTYPING_DEPTH {
654            self.can_subtype.push(index);
655        }
656
657        self.types.push(ty);
658        index
659    }
660
661    fn arbitrary_rec_group(
662        &mut self,
663        u: &mut Unstructured,
664        kind: AllowEmptyRecGroup,
665    ) -> Result<()> {
666        let rec_group_start = self.types.len();
667
668        assert!(matches!(self.max_type_limit, MaxTypeLimit::ModuleTypes));
669
670        if self.config.gc_enabled {
671            // With small probability, clone an existing rec group.
672            if self.rec_groups.len() > 0 && u.ratio(1, u8::MAX)? {
673                return self.clone_rec_group(u, kind);
674            }
675
676            // Otherwise, create a new rec group with multiple types inside.
677            let max_rec_group_size = self.config.max_types - self.types.len();
678            let min_rec_group_size = match kind {
679                AllowEmptyRecGroup::Yes => 0,
680                AllowEmptyRecGroup::No => 1,
681            };
682            let rec_group_size = u.int_in_range(min_rec_group_size..=max_rec_group_size)?;
683            let type_ref_limit = u32::try_from(self.types.len() + rec_group_size).unwrap();
684            self.max_type_limit = MaxTypeLimit::Num(type_ref_limit);
685            for _ in 0..rec_group_size {
686                let ty = self.arbitrary_sub_type(u)?;
687                self.add_type(ty);
688            }
689        } else {
690            let type_ref_limit = u32::try_from(self.types.len()).unwrap();
691            self.max_type_limit = MaxTypeLimit::Num(type_ref_limit);
692            let ty = self.arbitrary_sub_type(u)?;
693            self.add_type(ty);
694        }
695
696        self.max_type_limit = MaxTypeLimit::ModuleTypes;
697
698        self.rec_groups.push(rec_group_start..self.types.len());
699        Ok(())
700    }
701
702    fn clone_rec_group(&mut self, u: &mut Unstructured, kind: AllowEmptyRecGroup) -> Result<()> {
703        // Choose an arbitrary rec group to clone, but bail out if the selected
704        // rec group isn't valid to clone. For example if empty groups aren't
705        // allowed and the selected group is empty, or if cloning the rec group
706        // would cause the maximum number of types to be exceeded.
707        let group = u.choose(&self.rec_groups)?.clone();
708        if group.is_empty() && kind == AllowEmptyRecGroup::No {
709            return Ok(());
710        }
711        if group.len() > self.config.max_types.saturating_sub(self.types.len()) {
712            return Ok(());
713        }
714
715        // NB: this does *not* guarantee that the cloned rec group will
716        // canonicalize the same as the original rec group and be deduplicated.
717        // That would require a second pass over the cloned types to rewrite
718        // references within the original rec group to be references into the
719        // new rec group. That might make sense to do one day, but for now we
720        // don't do it. That also means that we can't mark the new types as
721        // "subtypes" of the old types and vice versa.
722        let new_rec_group_start = self.types.len();
723        for index in group {
724            let orig_ty_index = u32::try_from(index).unwrap();
725            let ty = self.ty(orig_ty_index).clone();
726            self.add_type(ty);
727        }
728        self.rec_groups.push(new_rec_group_start..self.types.len());
729        Ok(())
730    }
731
732    fn arbitrary_sub_type(&mut self, u: &mut Unstructured) -> Result<SubType> {
733        if !self.config.gc_enabled {
734            let shared = self.arbitrary_shared(u)?;
735            let func_type = self.propagate_shared(shared, |m| m.arbitrary_func_type(u))?;
736            let composite_type = CompositeType {
737                inner: CompositeInnerType::Func(func_type),
738                shared,
739                descriptor: None,
740                describes: None,
741            };
742            return Ok(SubType {
743                is_final: true,
744                supertype: None,
745                composite_type,
746                depth: 1,
747            });
748        }
749
750        if !self.can_subtype.is_empty() && u.ratio(1, 32_u8)? {
751            self.arbitrary_sub_type_of_super_type(u)
752        } else {
753            Ok(SubType {
754                is_final: u.arbitrary()?,
755                supertype: None,
756                composite_type: self.arbitrary_composite_type(u)?,
757                depth: 1,
758            })
759        }
760    }
761
762    fn arbitrary_sub_type_of_super_type(&mut self, u: &mut Unstructured) -> Result<SubType> {
763        let supertype = *u.choose(&self.can_subtype)?;
764        let mut composite_type = self.types[usize::try_from(supertype).unwrap()]
765            .composite_type
766            .clone();
767        match &mut composite_type.inner {
768            CompositeInnerType::Array(a) => {
769                a.0 = self.arbitrary_matching_field_type(u, a.0)?;
770            }
771            CompositeInnerType::Func(f) => {
772                *f = self.arbitrary_matching_func_type(u, f)?;
773            }
774            CompositeInnerType::Struct(s) => {
775                *s = self.propagate_shared(composite_type.shared, |m| {
776                    m.arbitrary_matching_struct_type(u, s)
777                })?;
778            }
779        }
780        Ok(SubType {
781            is_final: u.arbitrary()?,
782            supertype: Some(supertype),
783            composite_type,
784            depth: 1 + self.types[supertype as usize].depth,
785        })
786    }
787
788    fn arbitrary_matching_struct_type(
789        &mut self,
790        u: &mut Unstructured,
791        ty: &StructType,
792    ) -> Result<StructType> {
793        let len_extra_fields = u.int_in_range(0..=5)?;
794        let mut fields = Vec::with_capacity(ty.fields.len() + len_extra_fields);
795        for field in ty.fields.iter() {
796            fields.push(self.arbitrary_matching_field_type(u, *field)?);
797        }
798        for _ in 0..len_extra_fields {
799            fields.push(self.arbitrary_field_type(u)?);
800        }
801        Ok(StructType {
802            fields: fields.into_boxed_slice(),
803        })
804    }
805
806    fn arbitrary_matching_field_type(
807        &mut self,
808        u: &mut Unstructured,
809        ty: FieldType,
810    ) -> Result<FieldType> {
811        if ty.mutable {
812            Ok(ty)
813        } else {
814            Ok(FieldType {
815                element_type: self.arbitrary_matching_storage_type(u, ty.element_type)?,
816                mutable: false,
817            })
818        }
819    }
820
821    fn arbitrary_matching_storage_type(
822        &mut self,
823        u: &mut Unstructured,
824        ty: StorageType,
825    ) -> Result<StorageType> {
826        match ty {
827            StorageType::I8 => Ok(StorageType::I8),
828            StorageType::I16 => Ok(StorageType::I16),
829            StorageType::Val(ty) => Ok(StorageType::Val(self.arbitrary_matching_val_type(u, ty)?)),
830        }
831    }
832
833    fn arbitrary_matching_val_type(
834        &mut self,
835        u: &mut Unstructured,
836        ty: ValType,
837    ) -> Result<ValType> {
838        match ty {
839            ValType::I32 => Ok(ValType::I32),
840            ValType::I64 => Ok(ValType::I64),
841            ValType::F32 => Ok(ValType::F32),
842            ValType::F64 => Ok(ValType::F64),
843            ValType::V128 => Ok(ValType::V128),
844            ValType::Ref(ty) => Ok(ValType::Ref(self.arbitrary_matching_ref_type(u, ty)?)),
845        }
846    }
847
848    fn arbitrary_matching_ref_type(&self, u: &mut Unstructured, ty: RefType) -> Result<RefType> {
849        Ok(RefType {
850            nullable: ty.nullable,
851            heap_type: self.arbitrary_matching_heap_type(u, ty.heap_type)?,
852        })
853    }
854
855    fn arbitrary_matching_heap_type(&self, u: &mut Unstructured, ty: HeapType) -> Result<HeapType> {
856        use {AbstractHeapType as AHT, CompositeInnerType as CT, HeapType as HT};
857
858        if !self.config.gc_enabled {
859            return Ok(ty);
860        }
861
862        let mut choices = vec![ty];
863        match ty {
864            HT::Abstract { shared, ty } => {
865                use AbstractHeapType::*;
866                let add_abstract = |choices: &mut Vec<HT>, tys: &[AHT]| {
867                    choices.extend(tys.iter().map(|&ty| HT::Abstract { shared, ty }));
868                };
869                let add_concrete = |choices: &mut Vec<HT>, tys: &[u32]| {
870                    choices.extend(
871                        tys.iter()
872                            .filter(|&&idx| shared == self.is_shared_type(idx))
873                            .copied()
874                            .map(HT::Concrete),
875                    );
876                };
877                match ty {
878                    Any => {
879                        add_abstract(&mut choices, &[Eq, Struct, Array, I31, None]);
880                        add_concrete(&mut choices, &self.array_types);
881                        add_concrete(&mut choices, &self.struct_types);
882                    }
883                    Eq => {
884                        add_abstract(&mut choices, &[Struct, Array, I31, None]);
885                        add_concrete(&mut choices, &self.array_types);
886                        add_concrete(&mut choices, &self.struct_types);
887                    }
888                    Struct => {
889                        add_abstract(&mut choices, &[Struct, None]);
890                        add_concrete(&mut choices, &self.struct_types);
891                    }
892                    Array => {
893                        add_abstract(&mut choices, &[Array, None]);
894                        add_concrete(&mut choices, &self.array_types);
895                    }
896                    I31 => {
897                        add_abstract(&mut choices, &[None]);
898                    }
899                    Func => {
900                        add_abstract(&mut choices, &[NoFunc]);
901                        add_concrete(&mut choices, &self.func_types);
902                    }
903                    Extern => {
904                        add_abstract(&mut choices, &[NoExtern]);
905                    }
906                    Exn | NoExn | None | NoExtern | NoFunc | Cont | NoCont => {}
907                }
908            }
909            HT::Concrete(idx) => {
910                if let Some(subs) = self.super_to_sub_types.get(&idx) {
911                    choices.extend(subs.iter().copied().map(HT::Concrete));
912                }
913                if self.config.custom_descriptors_enabled {
914                    choices.push(HT::Exact(idx));
915                    if let Some(subs) = self.super_to_sub_types.get(&idx) {
916                        choices.extend(subs.iter().copied().map(HT::Concrete));
917                    }
918                }
919                match self
920                    .types
921                    .get(usize::try_from(idx).unwrap())
922                    .map(|ty| (ty.composite_type.shared, &ty.composite_type.inner))
923                {
924                    Some((shared, CT::Array(_) | CT::Struct(_))) => choices.push(HT::Abstract {
925                        shared,
926                        ty: AbstractHeapType::None,
927                    }),
928                    Some((shared, CT::Func(_))) => choices.push(HT::Abstract {
929                        shared,
930                        ty: AbstractHeapType::NoFunc,
931                    }),
932                    None => {
933                        // The referenced type might be part of this same rec
934                        // group we are currently generating, but not generated
935                        // yet. In this case, leave `choices` as it is, and we
936                        // will just end up choosing the original type again
937                        // down below, which is fine.
938                    }
939                }
940            }
941            HT::Exact(_) => (),
942        }
943        Ok(*u.choose(&choices)?)
944    }
945
946    fn arbitrary_matching_func_type(
947        &mut self,
948        u: &mut Unstructured,
949        ty: &FuncType,
950    ) -> Result<Rc<FuncType>> {
951        // Note: parameters are contravariant, results are covariant. See
952        // https://github.com/bytecodealliance/wasm-tools/blob/0616ef196a183cf137ee06b4a5993b7d590088bf/crates/wasmparser/src/readers/core/types/matches.rs#L137-L174
953        // for details.
954        let mut params = Vec::with_capacity(ty.params.len());
955        for param in &ty.params {
956            params.push(self.arbitrary_super_type_of_val_type(u, *param)?);
957        }
958        let mut results = Vec::with_capacity(ty.results.len());
959        for result in &ty.results {
960            results.push(self.arbitrary_matching_val_type(u, *result)?);
961        }
962        Ok(Rc::new(FuncType { params, results }))
963    }
964
965    fn arbitrary_super_type_of_val_type(
966        &mut self,
967        u: &mut Unstructured,
968        ty: ValType,
969    ) -> Result<ValType> {
970        match ty {
971            ValType::I32 => Ok(ValType::I32),
972            ValType::I64 => Ok(ValType::I64),
973            ValType::F32 => Ok(ValType::F32),
974            ValType::F64 => Ok(ValType::F64),
975            ValType::V128 => Ok(ValType::V128),
976            ValType::Ref(ty) => Ok(ValType::Ref(self.arbitrary_super_type_of_ref_type(u, ty)?)),
977        }
978    }
979
980    fn arbitrary_super_type_of_ref_type(
981        &self,
982        u: &mut Unstructured,
983        ty: RefType,
984    ) -> Result<RefType> {
985        Ok(RefType {
986            // TODO: For now, only create allow nullable reference
987            // types. Eventually we should support non-nullable reference types,
988            // but this means that we will also need to recognize when it is
989            // impossible to create an instance of the reference (eg `(ref
990            // nofunc)` has no instances, and self-referential types that
991            // contain a non-null self-reference are also impossible to create).
992            nullable: true,
993            heap_type: self.arbitrary_super_type_of_heap_type(u, ty.heap_type)?,
994        })
995    }
996
997    fn arbitrary_super_type_of_heap_type(
998        &self,
999        u: &mut Unstructured,
1000        ty: HeapType,
1001    ) -> Result<HeapType> {
1002        use {AbstractHeapType as AHT, CompositeInnerType as CT, HeapType as HT};
1003
1004        if !self.config.gc_enabled {
1005            return Ok(ty);
1006        }
1007
1008        let mut choices = vec![ty];
1009        match ty {
1010            HT::Abstract { shared, ty } => {
1011                use AbstractHeapType::*;
1012                let add_abstract = |choices: &mut Vec<HT>, tys: &[AHT]| {
1013                    choices.extend(tys.iter().map(|&ty| HT::Abstract { shared, ty }));
1014                };
1015                let add_concrete = |choices: &mut Vec<HT>, tys: &[u32]| {
1016                    choices.extend(
1017                        tys.iter()
1018                            .filter(|&&idx| shared == self.is_shared_type(idx))
1019                            .copied()
1020                            .map(HT::Concrete),
1021                    );
1022                };
1023                match ty {
1024                    None => {
1025                        add_abstract(&mut choices, &[Any, Eq, Struct, Array, I31]);
1026                        add_concrete(&mut choices, &self.array_types);
1027                        add_concrete(&mut choices, &self.struct_types);
1028                    }
1029                    NoExtern => {
1030                        add_abstract(&mut choices, &[Extern]);
1031                    }
1032                    NoFunc => {
1033                        add_abstract(&mut choices, &[Func]);
1034                        add_concrete(&mut choices, &self.func_types);
1035                    }
1036                    NoExn => {
1037                        add_abstract(&mut choices, &[Exn]);
1038                    }
1039                    Struct | Array | I31 => {
1040                        add_abstract(&mut choices, &[Any, Eq]);
1041                    }
1042                    Eq => {
1043                        add_abstract(&mut choices, &[Any]);
1044                    }
1045                    NoCont => {
1046                        add_abstract(&mut choices, &[Cont]);
1047                    }
1048                    Exn | Any | Func | Extern | Cont => {}
1049                }
1050            }
1051            HT::Concrete(mut idx) => {
1052                if let Some(sub_ty) = &self.types.get(usize::try_from(idx).unwrap()) {
1053                    use AbstractHeapType::*;
1054                    let ht = |ty| HT::Abstract {
1055                        shared: sub_ty.composite_type.shared,
1056                        ty,
1057                    };
1058                    match &sub_ty.composite_type.inner {
1059                        CT::Array(_) => {
1060                            choices.extend([ht(Any), ht(Eq), ht(Array)]);
1061                        }
1062                        CT::Func(_) => {
1063                            choices.push(ht(Func));
1064                        }
1065                        CT::Struct(_) => {
1066                            choices.extend([ht(Any), ht(Eq), ht(Struct)]);
1067                        }
1068                    }
1069                } else {
1070                    // Same as in `arbitrary_matching_heap_type`: this was a
1071                    // forward reference to a concrete type that is part of
1072                    // this same rec group we are generating right now, and
1073                    // therefore we haven't generated that type yet. Just
1074                    // leave `choices` as it is and we will choose the
1075                    // original type again down below.
1076                }
1077                while let Some(supertype) = self
1078                    .types
1079                    .get(usize::try_from(idx).unwrap())
1080                    .and_then(|ty| ty.supertype)
1081                {
1082                    choices.push(HT::Concrete(supertype));
1083                    idx = supertype;
1084                }
1085            }
1086            HT::Exact(_) => (),
1087        }
1088        Ok(*u.choose(&choices)?)
1089    }
1090
1091    fn arbitrary_composite_type(&mut self, u: &mut Unstructured) -> Result<CompositeType> {
1092        use CompositeInnerType as CT;
1093        let shared = self.arbitrary_shared(u)?;
1094
1095        if !self.config.gc_enabled {
1096            return Ok(CompositeType {
1097                shared,
1098                inner: CT::Func(self.propagate_shared(shared, |m| m.arbitrary_func_type(u))?),
1099                descriptor: None,
1100                describes: None,
1101            });
1102        }
1103
1104        match u.int_in_range(0..=2)? {
1105            0 => Ok(CompositeType {
1106                shared,
1107                inner: CT::Array(ArrayType(
1108                    self.propagate_shared(shared, |m| m.arbitrary_field_type(u))?,
1109                )),
1110                descriptor: None,
1111                describes: None,
1112            }),
1113            1 => Ok(CompositeType {
1114                shared,
1115                inner: CT::Func(self.propagate_shared(shared, |m| m.arbitrary_func_type(u))?),
1116                descriptor: None,
1117                describes: None,
1118            }),
1119            2 => Ok(CompositeType {
1120                shared,
1121                inner: CT::Struct(self.propagate_shared(shared, |m| m.arbitrary_struct_type(u))?),
1122                descriptor: None, // TODO generate descriptor info when custom_descriptors_enabled
1123                describes: None,
1124            }),
1125            _ => unreachable!(),
1126        }
1127    }
1128
1129    fn arbitrary_struct_type(&mut self, u: &mut Unstructured) -> Result<StructType> {
1130        let len = u.int_in_range(0..=20)?;
1131        let mut fields = Vec::with_capacity(len);
1132        for _ in 0..len {
1133            fields.push(self.arbitrary_field_type(u)?);
1134        }
1135        Ok(StructType {
1136            fields: fields.into_boxed_slice(),
1137        })
1138    }
1139
1140    fn arbitrary_field_type(&mut self, u: &mut Unstructured) -> Result<FieldType> {
1141        Ok(FieldType {
1142            element_type: self.arbitrary_storage_type(u)?,
1143            mutable: u.arbitrary()?,
1144        })
1145    }
1146
1147    fn arbitrary_storage_type(&mut self, u: &mut Unstructured) -> Result<StorageType> {
1148        match u.int_in_range(0..=2)? {
1149            0 => Ok(StorageType::I8),
1150            1 => Ok(StorageType::I16),
1151            2 => Ok(StorageType::Val(self.arbitrary_valtype(u)?)),
1152            _ => unreachable!(),
1153        }
1154    }
1155
1156    fn arbitrary_ref_type(&self, u: &mut Unstructured) -> Result<RefType> {
1157        if !self.config.reference_types_enabled {
1158            return Ok(RefType::FUNCREF);
1159        }
1160        Ok(RefType {
1161            nullable: true,
1162            heap_type: self.arbitrary_heap_type(u)?,
1163        })
1164    }
1165
1166    fn arbitrary_heap_type(&self, u: &mut Unstructured) -> Result<HeapType> {
1167        assert!(self.config.reference_types_enabled);
1168
1169        let concrete_type_limit = match self.max_type_limit {
1170            MaxTypeLimit::Num(n) => n,
1171            MaxTypeLimit::ModuleTypes => u32::try_from(self.types.len()).unwrap(),
1172        };
1173
1174        if self.config.gc_enabled && concrete_type_limit > 0 && u.arbitrary()? {
1175            let idx = u.int_in_range(0..=concrete_type_limit - 1)?;
1176            // If the caller is demanding a shared heap type but the concrete
1177            // type we found is not in fact shared, we skip down below to use an
1178            // abstract heap type instead. If the caller is not demanding a
1179            // shared type, though, we can use either a shared or unshared
1180            // concrete type.
1181            if let Some(ty) = self.types.get(idx as usize) {
1182                // TODO: in the future, once we can easily query a list of
1183                // existing shared types, remove this extra check.
1184                if !(self.must_share && !ty.composite_type.shared) {
1185                    return Ok(HeapType::Concrete(idx));
1186                }
1187            }
1188        }
1189
1190        use AbstractHeapType::*;
1191        let mut choices = vec![Func, Extern];
1192        if self.config.exceptions_enabled {
1193            choices.push(Exn);
1194        }
1195        if self.config.gc_enabled {
1196            choices.extend(
1197                [Any, None, NoExtern, NoFunc, Eq, Struct, Array, I31]
1198                    .iter()
1199                    .copied(),
1200            );
1201        }
1202
1203        Ok(HeapType::Abstract {
1204            shared: self.arbitrary_shared(u)?,
1205            ty: *u.choose(&choices)?,
1206        })
1207    }
1208
1209    fn arbitrary_func_type(&mut self, u: &mut Unstructured) -> Result<Rc<FuncType>> {
1210        let mut params = vec![];
1211        let mut results = vec![];
1212        let max_params = 20;
1213        arbitrary_loop(u, 0, max_params, |u| {
1214            params.push(self.arbitrary_valtype(u)?);
1215            Ok(true)
1216        })?;
1217        let max_results = if self.config.multi_value_enabled {
1218            max_params
1219        } else {
1220            1
1221        };
1222        arbitrary_loop(u, 0, max_results, |u| {
1223            results.push(self.arbitrary_valtype(u)?);
1224            Ok(true)
1225        })?;
1226        Ok(Rc::new(FuncType { params, results }))
1227    }
1228
1229    fn can_add_local_or_import_tag(&self) -> bool {
1230        self.config.exceptions_enabled
1231            && self.has_tag_func_types()
1232            && self.tags.len() < self.config.max_tags
1233    }
1234
1235    fn can_add_local_or_import_func(&self) -> bool {
1236        !self.func_types.is_empty() && self.funcs.len() < self.config.max_funcs
1237    }
1238
1239    fn can_add_local_or_import_table(&self) -> bool {
1240        self.tables.len() < self.config.max_tables
1241    }
1242
1243    fn can_add_local_or_import_global(&self) -> bool {
1244        self.globals.len() < self.config.max_globals
1245    }
1246
1247    fn can_add_local_or_import_memory(&self) -> bool {
1248        self.memories.len() < self.config.max_memories
1249    }
1250
1251    fn imports_exports_from_module_shape(&mut self, u: &mut Unstructured) -> Result<bool> {
1252        let example_module = if let Some(wasm) = self.config.module_shape.clone() {
1253            wasm
1254        } else {
1255            return Ok(false);
1256        };
1257
1258        #[cfg(feature = "wasmparser")]
1259        {
1260            self._imports_exports_from_module_shape(u, &example_module)?;
1261            Ok(true)
1262        }
1263        #[cfg(not(feature = "wasmparser"))]
1264        {
1265            let _ = (example_module, u);
1266            panic!("support for `module_shape` was disabled at compile time");
1267        }
1268    }
1269
1270    #[cfg(feature = "wasmparser")]
1271    fn _imports_exports_from_module_shape(
1272        &mut self,
1273        u: &mut Unstructured,
1274        example_module: &[u8],
1275    ) -> Result<()> {
1276        // First, we validate the module-by-example and extract the required types, imports
1277        // and exports. Besides, we also extract the functions, tags, tables, memories and
1278        // globals that are necessary for generating the exports.
1279        let mut available_funcs: Vec<u32> = Vec::new();
1280        let mut available_tags: Vec<wasmparser::TagType> = Vec::new();
1281        let mut available_tables: Vec<wasmparser::TableType> = Vec::new();
1282        let mut available_globals: Vec<wasmparser::GlobalType> = Vec::new();
1283        let mut available_memories: Vec<wasmparser::MemoryType> = Vec::new();
1284
1285        let mut required_types: Vec<SubType> = Vec::new();
1286        let mut required_recgrps: Vec<usize> = Vec::new();
1287        let mut required_imports: Vec<wasmparser::Imports> = Vec::new();
1288        let mut required_exports: Vec<wasmparser::Export> = Vec::new();
1289        let mut validator = wasmparser::Validator::new();
1290        validator
1291            .validate_all(example_module)
1292            .expect("Failed to validate `module_shape` module");
1293        for payload in wasmparser::Parser::new(0).parse_all(&example_module) {
1294            match payload.expect("could not parse the `module_shape` module") {
1295                wasmparser::Payload::TypeSection(type_reader) => {
1296                    for recgrp in type_reader {
1297                        let recgrp = recgrp.expect("could not read recursive group");
1298                        required_recgrps.push(recgrp.types().len());
1299                        for subtype in recgrp.into_types() {
1300                            let mut subtype: SubType = subtype.try_into().unwrap();
1301                            if let Some(supertype_idx) = subtype.supertype {
1302                                subtype.depth = required_types[supertype_idx as usize].depth + 1;
1303                            }
1304                            required_types.push(subtype);
1305                        }
1306                    }
1307                }
1308                wasmparser::Payload::ImportSection(import_reader) => {
1309                    for imports in import_reader {
1310                        required_imports.push(imports.expect("could not read imports"));
1311                    }
1312                }
1313                wasmparser::Payload::ExportSection(export_reader) => {
1314                    for ex in export_reader {
1315                        let ex = ex.expect("could not read export");
1316                        required_exports.push(ex);
1317                    }
1318                }
1319                wasmparser::Payload::FunctionSection(function_reader) => {
1320                    for func in function_reader {
1321                        let func = func.expect("could not read function");
1322                        available_funcs.push(func);
1323                    }
1324                }
1325                wasmparser::Payload::TagSection(tag_reader) => {
1326                    for tag in tag_reader {
1327                        let tag = tag.expect("could not read tag");
1328                        available_tags.push(tag);
1329                    }
1330                }
1331                wasmparser::Payload::TableSection(table_reader) => {
1332                    for table in table_reader {
1333                        let table = table.expect("could not read table");
1334                        available_tables.push(table.ty);
1335                    }
1336                }
1337                wasmparser::Payload::MemorySection(memory_reader) => {
1338                    for memory in memory_reader {
1339                        let memory = memory.expect("could not read memory");
1340                        available_memories.push(memory);
1341                    }
1342                }
1343                wasmparser::Payload::GlobalSection(global_reader) => {
1344                    for global in global_reader {
1345                        let global = global.expect("could not read global");
1346                        available_globals.push(global.ty);
1347                    }
1348                }
1349                _ => {}
1350            }
1351        }
1352
1353        // Next, we copy all the types from the module-by-example into current module. This is necessary
1354        // to ensure that the current module has all the types it needs to type-check correctly.
1355        let mut recgrp_start_idx = self.types.len();
1356        for size in required_recgrps {
1357            self.rec_groups
1358                .push(recgrp_start_idx..recgrp_start_idx + size);
1359            recgrp_start_idx += size;
1360        }
1361        for ty in &required_types {
1362            self.add_type(ty.clone());
1363        }
1364
1365        // We then generate import entries which refer to the imported types. Additionally, we add the
1366        // imported items to their corresponding vectors here, ensuring that exports reference the
1367        // correct items.
1368        let mut imported_funcs: Vec<u32> = Vec::new();
1369        let mut imported_tags: Vec<wasmparser::TagType> = Vec::new();
1370        let mut imported_tables: Vec<wasmparser::TableType> = Vec::new();
1371        let mut imported_globals: Vec<wasmparser::GlobalType> = Vec::new();
1372        let mut imported_memories: Vec<wasmparser::MemoryType> = Vec::new();
1373        fn entity_type(ty: wasmparser::TypeRef, required_types: &[SubType]) -> EntityType {
1374            match ty {
1375                wasmparser::TypeRef::Func(sig_idx) => {
1376                    let ty = required_types
1377                        .get(sig_idx as usize)
1378                        .expect("signature index refers to a type out of bounds");
1379                    EntityType::Func(sig_idx, Rc::clone(ty.composite_type.unwrap_func()))
1380                }
1381                wasmparser::TypeRef::FuncExact(_) => panic!("Unexpected func_exact import"),
1382                wasmparser::TypeRef::Tag(ty) => {
1383                    let func_type = required_types
1384                        .get(ty.func_type_idx as usize)
1385                        .expect("function type index for tag refers to a type out of bounds")
1386                        .composite_type
1387                        .unwrap_func();
1388                    EntityType::Tag(TagType {
1389                        func_type_idx: ty.func_type_idx,
1390                        func_type: Rc::clone(func_type),
1391                    })
1392                }
1393                wasmparser::TypeRef::Table(ty) => EntityType::Table(ty.try_into().unwrap()),
1394                wasmparser::TypeRef::Memory(ty) => EntityType::Memory(ty.into()),
1395                wasmparser::TypeRef::Global(ty) => EntityType::Global(ty.try_into().unwrap()),
1396            }
1397        }
1398        let mut translate_import = |import: wasmparser::Import| {
1399            let parser_ty = import.ty;
1400            let ty = entity_type(parser_ty, &required_types);
1401            match (parser_ty, &ty) {
1402                (wasmparser::TypeRef::Func(sig_idx), EntityType::Func(_, func_type)) => {
1403                    imported_funcs.push(sig_idx);
1404                    self.funcs.push((sig_idx, Rc::clone(func_type)));
1405                }
1406                (wasmparser::TypeRef::Tag(parser_ty), EntityType::Tag(tag_type)) => {
1407                    imported_tags.push(parser_ty);
1408                    self.tags.push(tag_type.clone());
1409                }
1410                (wasmparser::TypeRef::Table(parser_ty), EntityType::Table(ty)) => {
1411                    imported_tables.push(parser_ty);
1412                    self.tables.push(*ty);
1413                }
1414                (wasmparser::TypeRef::Memory(parser_ty), EntityType::Memory(ty)) => {
1415                    imported_memories.push(parser_ty);
1416                    self.memories.push(*ty);
1417                }
1418                (wasmparser::TypeRef::Global(parser_ty), EntityType::Global(ty)) => {
1419                    imported_globals.push(parser_ty);
1420                    self.globals.push(*ty);
1421                }
1422                _ => unreachable!(),
1423            }
1424            self.num_imports += 1;
1425            Import {
1426                module: import.module.to_string(),
1427                name: import.name.to_string(),
1428                entity_type: ty,
1429            }
1430        };
1431
1432        for imports in required_imports {
1433            match imports {
1434                wasmparser::Imports::Single(_, import) => {
1435                    self.imports.push(Imports::Single(translate_import(import)));
1436                }
1437                wasmparser::Imports::Compact1 { module, items } => {
1438                    let items = items
1439                        .into_iter()
1440                        .map(|item| {
1441                            let item = item.expect("could not read compact import");
1442                            translate_import(wasmparser::Import {
1443                                module,
1444                                name: item.name,
1445                                ty: item.ty,
1446                            })
1447                        })
1448                        .collect::<Vec<_>>();
1449                    if self.config.compact_imports_enabled {
1450                        if !items.is_empty() {
1451                            self.imports.push(Imports::Compact1 {
1452                                module: module.to_string(),
1453                                items,
1454                            });
1455                        }
1456                    } else {
1457                        self.imports.extend(items.into_iter().map(Imports::Single));
1458                    }
1459                }
1460                wasmparser::Imports::Compact2 { module, ty, names } => {
1461                    let items = names
1462                        .into_iter()
1463                        .map(|name| {
1464                            translate_import(wasmparser::Import {
1465                                module,
1466                                name: name.expect("could not read compact import name"),
1467                                ty,
1468                            })
1469                        })
1470                        .collect::<Vec<_>>();
1471                    if self.config.compact_imports_enabled {
1472                        if !items.is_empty() {
1473                            self.imports.push(Imports::Compact2 {
1474                                module: module.to_string(),
1475                                entity_type: entity_type(ty, &required_types),
1476                                names: items.into_iter().map(|item| item.name).collect(),
1477                            });
1478                        }
1479                    } else {
1480                        self.imports.extend(items.into_iter().map(Imports::Single));
1481                    }
1482                }
1483            }
1484        }
1485        available_tags.splice(0..0, imported_tags);
1486        available_funcs.splice(0..0, imported_funcs);
1487        available_tables.splice(0..0, imported_tables);
1488        available_globals.splice(0..0, imported_globals);
1489        available_memories.splice(0..0, imported_memories);
1490
1491        // Next, we generate export entries which refer to the export specifications.
1492        for export in required_exports {
1493            let index = match export.kind {
1494                wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1495                    match available_funcs.get(export.index as usize) {
1496                        None => panic!("function index out of bounds"),
1497                        Some(sig_idx) => match required_types.get(*sig_idx as usize) {
1498                            None => panic!("signature index refers to a type out of bounds"),
1499                            Some(ty) => match &ty.composite_type.inner {
1500                                CompositeInnerType::Func(func_type) => {
1501                                    let func_index = self.funcs.len() as u32;
1502                                    self.funcs.push((*sig_idx, Rc::clone(func_type)));
1503                                    self.num_defined_funcs += 1;
1504                                    func_index
1505                                }
1506                                _ => panic!("a function type is required for function export"),
1507                            },
1508                        },
1509                    }
1510                }
1511
1512                wasmparser::ExternalKind::Tag => match available_tags.get(export.index as usize) {
1513                    None => panic!("tag index out of bounds"),
1514                    Some(wasmparser::TagType { func_type_idx, .. }) => {
1515                        match required_types.get(*func_type_idx as usize) {
1516                            None => {
1517                                panic!("function type index for tag refers to a type out of bounds")
1518                            }
1519                            Some(ty) => match &ty.composite_type.inner {
1520                                CompositeInnerType::Func(func_type) => {
1521                                    let tag_index = self.tags.len() as u32;
1522                                    self.tags.push(TagType {
1523                                        func_type_idx: *func_type_idx,
1524                                        func_type: Rc::clone(func_type),
1525                                    });
1526                                    self.num_defined_tags += 1;
1527                                    tag_index
1528                                }
1529                                _ => panic!("a function type is required for tag export"),
1530                            },
1531                        }
1532                    }
1533                },
1534
1535                wasmparser::ExternalKind::Table => {
1536                    match available_tables.get(export.index as usize) {
1537                        None => panic!("table index out of bounds"),
1538                        Some(ty) => {
1539                            self.add_arbitrary_table_of_type((*ty).try_into().unwrap(), u)?
1540                        }
1541                    }
1542                }
1543
1544                wasmparser::ExternalKind::Memory => {
1545                    match available_memories.get(export.index as usize) {
1546                        None => panic!("memory index out of bounds"),
1547                        Some(ty) => self.add_arbitrary_memory_of_type((*ty).into())?,
1548                    }
1549                }
1550
1551                wasmparser::ExternalKind::Global => {
1552                    match available_globals.get(export.index as usize) {
1553                        None => panic!("global index out of bounds"),
1554                        Some(ty) => {
1555                            self.add_arbitrary_global_of_type((*ty).try_into().unwrap(), u)?
1556                        }
1557                    }
1558                }
1559            };
1560            self.exports
1561                .push((export.name.to_string(), export.kind.into(), index));
1562            self.export_names.insert(export.name.to_string());
1563        }
1564
1565        Ok(())
1566    }
1567
1568    fn arbitrary_imports(&mut self, u: &mut Unstructured) -> Result<()> {
1569        if self.num_imports > self.config.max_imports || self.type_size > self.config.max_type_size
1570        {
1571            return Err(arbitrary::Error::IncorrectFormat);
1572        }
1573
1574        let mut import_names = HashSet::new();
1575        let mut entity_generation_failed = false;
1576        while !entity_generation_failed && self.num_imports < self.config.max_imports {
1577            let reached_min_imports = self.num_imports >= self.config.min_imports;
1578            if reached_min_imports {
1579                let keep_going = u.arbitrary().unwrap_or(false);
1580                if !keep_going {
1581                    break;
1582                }
1583            }
1584
1585            let import_kind = self.arbitrary_import_group_kind(u)?;
1586            let module = limited_string(1_000, u)?;
1587            match import_kind {
1588                ImportsKind::Single => {
1589                    let Some(entity_type) = self.arbitrary_import_entity_type(u)? else {
1590                        break;
1591                    };
1592                    let name = self.arbitrary_import_name(&module, &mut import_names, u)?;
1593                    self.commit_entity_type(&entity_type);
1594                    self.imports.push(Imports::Single(Import {
1595                        module,
1596                        name,
1597                        entity_type,
1598                    }));
1599                }
1600                ImportsKind::Compact1 => {
1601                    let mut items = Vec::new();
1602                    while self.num_imports < self.config.max_imports {
1603                        let keep_going = u.arbitrary().unwrap_or(false);
1604                        if !keep_going {
1605                            break;
1606                        }
1607
1608                        let Some(entity_type) = self.arbitrary_import_entity_type(u)? else {
1609                            // No entity kind is available, or generated entity hits config.max_type_size.
1610                            // We push the in-progress import entry, and stop generating imports.
1611                            entity_generation_failed = true;
1612                            break;
1613                        };
1614                        let name = self.arbitrary_import_name(&module, &mut import_names, u)?;
1615                        self.commit_entity_type(&entity_type);
1616                        items.push(Import {
1617                            module: module.clone(),
1618                            name,
1619                            entity_type,
1620                        });
1621                    }
1622                    if !items.is_empty() {
1623                        self.imports.push(Imports::Compact1 { module, items });
1624                    }
1625                }
1626                ImportsKind::Compact2 => {
1627                    let Some(entity_type) = self.arbitrary_import_entity_type(u)? else {
1628                        break;
1629                    };
1630
1631                    let mut names = Vec::new();
1632                    while self.num_imports < self.config.max_imports {
1633                        let keep_going = u.arbitrary().unwrap_or(false);
1634                        if !keep_going {
1635                            break;
1636                        }
1637
1638                        let remaining_type_size = self.config.max_type_size - self.type_size;
1639                        let import_type_size = entity_type.size() + 1;
1640                        if import_type_size > remaining_type_size
1641                            || !self.can_push_entity_type(&entity_type)
1642                        {
1643                            entity_generation_failed = true;
1644                            break;
1645                        }
1646
1647                        let name = self.arbitrary_import_name(&module, &mut import_names, u)?;
1648                        self.commit_entity_type(&entity_type);
1649                        names.push(name);
1650                    }
1651
1652                    if !names.is_empty() {
1653                        self.imports.push(Imports::Compact2 {
1654                            module,
1655                            entity_type,
1656                            names,
1657                        });
1658                    }
1659                }
1660            }
1661        }
1662
1663        if self.num_imports < self.config.min_imports {
1664            Err(arbitrary::Error::IncorrectFormat)
1665        } else {
1666            Ok(())
1667        }
1668    }
1669
1670    fn arbitrary_import_group_kind(&self, u: &mut Unstructured) -> Result<ImportsKind> {
1671        if self.config.compact_imports_enabled {
1672            u.arbitrary()
1673        } else {
1674            Ok(ImportsKind::Single)
1675        }
1676    }
1677
1678    /// Generate an entity type for an import.
1679    ///
1680    /// Returns `Ok(None)` if no supported entity kind can currently be added,
1681    /// or if the generated entity would exceed the remaining type-size budget.
1682    ///
1683    /// Returns an error if the input does not contain enough valid data to
1684    /// generate the entity.
1685    fn arbitrary_import_entity_type(&mut self, u: &mut Unstructured) -> Result<Option<EntityType>> {
1686        // Make a list of all currently-allowed entities, and choose one arbitrarily.
1687        type GenerateEntity = fn(&mut Unstructured, &mut Module) -> Result<EntityType>;
1688
1689        let mut choices: Vec<GenerateEntity> = Vec::new();
1690        if self.can_add_local_or_import_tag() {
1691            choices.push(|u, module| Ok(EntityType::Tag(module.arbitrary_tag_type(u)?)));
1692        }
1693        if self.can_add_local_or_import_func() {
1694            choices.push(|u, module| {
1695                let idx = *u.choose(&module.func_types)?;
1696                Ok(EntityType::Func(idx, Rc::clone(module.func_type(idx))))
1697            });
1698        }
1699        if self.can_add_local_or_import_global() {
1700            choices.push(|u, module| Ok(EntityType::Global(module.arbitrary_global_type(u)?)));
1701        }
1702        if self.can_add_local_or_import_memory() {
1703            choices
1704                .push(|u, module| Ok(EntityType::Memory(arbitrary_memtype(u, module.config())?)));
1705        }
1706        if self.can_add_local_or_import_table() {
1707            choices.push(|u, module| {
1708                Ok(EntityType::Table(arbitrary_table_type(
1709                    u,
1710                    module.config(),
1711                    Some(module),
1712                )?))
1713            });
1714        }
1715
1716        if choices.is_empty() {
1717            return Ok(None);
1718        }
1719        let generate = *u.choose(&choices)?;
1720        let entity_type = generate(u, self)?;
1721
1722        // Check that we have space for the type size of the chosen entity.
1723        let remaining_type_size = self.config.max_type_size - self.type_size;
1724        let import_type_size = entity_type.size() + 1;
1725        Ok((import_type_size <= remaining_type_size).then_some(entity_type))
1726    }
1727
1728    fn arbitrary_import_name(
1729        &self,
1730        module: &str,
1731        import_names: &mut HashSet<(String, String)>,
1732        u: &mut Unstructured,
1733    ) -> Result<String> {
1734        let mut import = (module.to_owned(), limited_string(1_000, u)?);
1735        match self.duplicate_imports_behavior {
1736            DuplicateImportsBehavior::Allowed => Ok(import.1),
1737            DuplicateImportsBehavior::Disallowed => {
1738                while import_names.contains(&import) {
1739                    use std::fmt::Write;
1740                    write!(&mut import.1, "{}", import_names.len()).unwrap();
1741                }
1742                import_names.insert(import.clone());
1743                Ok(import.1)
1744            }
1745        }
1746    }
1747
1748    /// Does the given `EntityType` have remaining capacity?
1749    fn can_push_entity_type(&self, entity_type: &EntityType) -> bool {
1750        match entity_type {
1751            EntityType::Tag(_) => self.tags.len() < self.config.max_tags,
1752            EntityType::Func(_, _) => self.funcs.len() < self.config.max_funcs,
1753            EntityType::Global(_) => self.globals.len() < self.config.max_globals,
1754            EntityType::Table(_) => self.tables.len() < self.config.max_tables,
1755            EntityType::Memory(_) => self.memories.len() < self.config.max_memories,
1756        }
1757    }
1758
1759    /// Push the given entity type, incrementing `self.type_size` and `self.num_imports`
1760    fn commit_entity_type(&mut self, entity_type: &EntityType) {
1761        self.type_size += entity_type.size() + 1;
1762        match entity_type {
1763            EntityType::Tag(ty) => self.tags.push(ty.clone()),
1764            EntityType::Func(idx, ty) => self.funcs.push((*idx, Rc::clone(ty))),
1765            EntityType::Global(ty) => self.globals.push(*ty),
1766            EntityType::Table(ty) => self.tables.push(*ty),
1767            EntityType::Memory(ty) => self.memories.push(*ty),
1768        }
1769        self.num_imports += 1;
1770    }
1771
1772    /// Generate some arbitrary imports from the list of available imports.
1773    ///
1774    /// Returns `true` if there was a list of available imports
1775    /// configured. Otherwise `false` and the caller should generate arbitrary
1776    /// imports.
1777    fn arbitrary_imports_from_available(&mut self, u: &mut Unstructured) -> Result<bool> {
1778        let example_module = if let Some(wasm) = self.config.available_imports.take() {
1779            wasm
1780        } else {
1781            return Ok(false);
1782        };
1783
1784        #[cfg(feature = "wasmparser")]
1785        {
1786            self._arbitrary_imports_from_available(u, &example_module)?;
1787            Ok(true)
1788        }
1789        #[cfg(not(feature = "wasmparser"))]
1790        {
1791            let _ = (example_module, u);
1792            panic!("support for `available_imports` was disabled at compile time");
1793        }
1794    }
1795
1796    #[cfg(feature = "wasmparser")]
1797    fn _arbitrary_imports_from_available(
1798        &mut self,
1799        u: &mut Unstructured,
1800        example_module: &[u8],
1801    ) -> Result<()> {
1802        // First, parse the module-by-example to collect the types and imports.
1803        //
1804        // `available_types` will map from a signature index (which is the same as the index into
1805        // this vector) as it appears in the parsed code, to the type itself. We copy all the types
1806        // from module-by-example into the module being constructed for the sake of simplicity
1807        // and for this reason, [`Self::config::max_types`] may be surpassed.
1808        let mut new_recgrps = Vec::<usize>::new();
1809        let mut available_types = Vec::<SubType>::new();
1810        let mut available_imports = Vec::<wasmparser::Import>::new();
1811        let mut validator = wasmparser::Validator::new();
1812        validator
1813            .validate_all(example_module)
1814            .expect("Failed to validate `module_shape` module");
1815        for payload in wasmparser::Parser::new(0).parse_all(&example_module) {
1816            match payload.expect("could not parse the available import payload") {
1817                wasmparser::Payload::TypeSection(type_reader) => {
1818                    for recgrp in type_reader {
1819                        let recgrp = recgrp.expect("could not read recursive group");
1820                        new_recgrps.push(recgrp.types().len());
1821                        for subtype in recgrp.into_types() {
1822                            let mut subtype: SubType = subtype.try_into().unwrap();
1823                            if let Some(supertype_idx) = subtype.supertype {
1824                                subtype.depth = available_types[supertype_idx as usize].depth + 1;
1825                            }
1826                            available_types.push(subtype);
1827                        }
1828                    }
1829                }
1830                wasmparser::Payload::ImportSection(import_reader) => {
1831                    for im in import_reader.into_imports() {
1832                        let im = im.expect("could not read import");
1833                        // We can immediately filter whether this is an import we want to
1834                        // use.
1835                        let use_import = u.arbitrary().unwrap_or(false);
1836                        if !use_import {
1837                            continue;
1838                        }
1839                        available_imports.push(im);
1840                    }
1841                }
1842                _ => {}
1843            }
1844        }
1845
1846        // We then generate import entries which refer to the imported types. Since this function
1847        // is called at the very beginning of the module generation process and all types from the
1848        // module-by-example are copied into the current module, no further adjustments are needed
1849        // for type indices.
1850        let mut new_imports = Vec::with_capacity(available_imports.len());
1851        for import in available_imports {
1852            let type_size_budget = self.config.max_type_size - self.type_size;
1853            let entity_type = match &import.ty {
1854                wasmparser::TypeRef::Func(sig_idx) => {
1855                    if self.funcs.len() >= self.config.max_funcs {
1856                        continue;
1857                    } else {
1858                        match available_types.get(*sig_idx as usize) {
1859                            None => panic!("signature index refers to a type out of bounds"),
1860                            Some(ty) => match &ty.composite_type.inner {
1861                                CompositeInnerType::Func(func_type) => {
1862                                    let entity = EntityType::Func(*sig_idx, Rc::clone(func_type));
1863                                    if type_size_budget < entity.size() {
1864                                        continue;
1865                                    }
1866                                    self.funcs.push((*sig_idx, Rc::clone(func_type)));
1867                                    entity
1868                                }
1869                                _ => panic!("a function type is required for function import"),
1870                            },
1871                        }
1872                    }
1873                }
1874
1875                wasmparser::TypeRef::FuncExact(_) => panic!("Unexpected func_exact import"),
1876
1877                wasmparser::TypeRef::Tag(wasmparser::TagType { func_type_idx, .. }) => {
1878                    let can_add_tag = self.tags.len() < self.config.max_tags;
1879                    if !self.config.exceptions_enabled || !can_add_tag {
1880                        continue;
1881                    } else {
1882                        match available_types.get(*func_type_idx as usize) {
1883                            None => {
1884                                panic!("function type index for tag refers to a type out of bounds")
1885                            }
1886                            Some(ty) => match &ty.composite_type.inner {
1887                                CompositeInnerType::Func(func_type) => {
1888                                    let tag_type = TagType {
1889                                        func_type_idx: *func_type_idx,
1890                                        func_type: Rc::clone(func_type),
1891                                    };
1892                                    let entity = EntityType::Tag(tag_type.clone());
1893                                    if type_size_budget < entity.size() {
1894                                        continue;
1895                                    }
1896                                    self.tags.push(tag_type);
1897                                    entity
1898                                }
1899                                _ => panic!("a function type is required for tag import"),
1900                            },
1901                        }
1902                    }
1903                }
1904
1905                wasmparser::TypeRef::Table(table_ty) => {
1906                    let table_ty = TableType::try_from(*table_ty).unwrap();
1907                    let entity = EntityType::Table(table_ty);
1908                    let type_size = entity.size();
1909                    if type_size_budget < type_size || !self.can_add_local_or_import_table() {
1910                        continue;
1911                    }
1912                    self.type_size += type_size;
1913                    self.tables.push(table_ty);
1914                    entity
1915                }
1916
1917                wasmparser::TypeRef::Memory(memory_ty) => {
1918                    let memory_ty = MemoryType::from(*memory_ty);
1919                    let entity = EntityType::Memory(memory_ty);
1920                    let type_size = entity.size();
1921                    if type_size_budget < type_size || !self.can_add_local_or_import_memory() {
1922                        continue;
1923                    }
1924                    self.type_size += type_size;
1925                    self.memories.push(memory_ty);
1926                    entity
1927                }
1928
1929                wasmparser::TypeRef::Global(global_ty) => {
1930                    let global_ty = GlobalType::try_from(*global_ty).unwrap();
1931                    let entity = EntityType::Global(global_ty);
1932                    let type_size = entity.size();
1933                    if type_size_budget < type_size || !self.can_add_local_or_import_global() {
1934                        continue;
1935                    }
1936                    self.type_size += type_size;
1937                    self.globals.push(global_ty);
1938                    entity
1939                }
1940            };
1941            new_imports.push(Import {
1942                module: import.module.to_string(),
1943                name: import.name.to_string(),
1944                entity_type,
1945            });
1946            self.num_imports += 1;
1947        }
1948
1949        // Finally, add the entities we just generated.
1950        let mut recgrp_start_idx = self.types.len();
1951        for size in new_recgrps {
1952            self.rec_groups
1953                .push(recgrp_start_idx..recgrp_start_idx + size);
1954            recgrp_start_idx += size;
1955        }
1956        for ty in available_types {
1957            self.add_type(ty);
1958        }
1959        self.push_arbitrary_import_groups(new_imports, u)?;
1960
1961        Ok(())
1962    }
1963
1964    /// Adds given imports to this module.
1965    ///
1966    /// If [`crate::Config::compact_imports_enabled`] is `true`,
1967    /// arbitrarily chooses a single import or a compact group,
1968    /// and arbitrarily collates consecutive imports with matching module
1969    /// and/or type into the same import group.
1970    ///
1971    /// If [`crate::Config::compact_imports_enabled`] is `false`,
1972    /// produces only single imports.
1973    #[cfg(feature = "wasmparser")]
1974    fn push_arbitrary_import_groups(
1975        &mut self,
1976        imports: Vec<Import>,
1977        u: &mut Unstructured,
1978    ) -> Result<()> {
1979        let mut imports = imports.into_iter().peekable();
1980        while let Some(import) = imports.next() {
1981            match self.arbitrary_import_group_kind(u)? {
1982                ImportsKind::Single => self.imports.push(Imports::Single(import)),
1983                ImportsKind::Compact1 => {
1984                    let module = import.module.clone();
1985                    let mut items = vec![import];
1986                    while imports.peek().is_some_and(|import| import.module == module)
1987                        && u.arbitrary().unwrap_or(false)
1988                    {
1989                        items.push(imports.next().unwrap());
1990                    }
1991                    self.imports.push(Imports::Compact1 { module, items });
1992                }
1993                ImportsKind::Compact2 => {
1994                    let module = import.module.clone();
1995                    let entity_type = import.entity_type.clone();
1996                    let mut names = vec![import.name];
1997                    while imports.peek().is_some_and(|import| {
1998                        import.module == module && import.entity_type == entity_type
1999                    }) && u.arbitrary().unwrap_or(false)
2000                    {
2001                        names.push(imports.next().unwrap().name);
2002                    }
2003                    self.imports.push(Imports::Compact2 {
2004                        module,
2005                        entity_type,
2006                        names,
2007                    });
2008                }
2009            }
2010        }
2011        Ok(())
2012    }
2013
2014    fn type_of(&self, kind: ExportKind, index: u32) -> EntityType {
2015        match kind {
2016            ExportKind::Global => EntityType::Global(self.globals[index as usize]),
2017            ExportKind::Memory => EntityType::Memory(self.memories[index as usize]),
2018            ExportKind::Table => EntityType::Table(self.tables[index as usize]),
2019            ExportKind::Func => {
2020                let (_idx, ty) = &self.funcs[index as usize];
2021                EntityType::Func(u32::MAX, ty.clone())
2022            }
2023            ExportKind::Tag => EntityType::Tag(self.tags[index as usize].clone()),
2024        }
2025    }
2026
2027    fn ty(&self, idx: u32) -> &SubType {
2028        &self.types[idx as usize]
2029    }
2030
2031    fn func_types(&self) -> impl Iterator<Item = (u32, &FuncType)> + '_ {
2032        self.func_types
2033            .iter()
2034            .copied()
2035            .map(move |type_i| (type_i, &**self.func_type(type_i)))
2036    }
2037
2038    fn func_type(&self, idx: u32) -> &Rc<FuncType> {
2039        match &self.ty(idx).composite_type.inner {
2040            CompositeInnerType::Func(f) => f,
2041            _ => panic!("types[{idx}] is not a func type"),
2042        }
2043    }
2044
2045    fn tags(&self) -> impl Iterator<Item = (u32, &TagType)> + '_ {
2046        self.tags
2047            .iter()
2048            .enumerate()
2049            .map(move |(i, ty)| (i as u32, ty))
2050    }
2051
2052    fn funcs(&self) -> impl Iterator<Item = (u32, &Rc<FuncType>)> + '_ {
2053        self.funcs
2054            .iter()
2055            .enumerate()
2056            .map(move |(i, (_, ty))| (i as u32, ty))
2057    }
2058
2059    fn has_tag_func_types(&self) -> bool {
2060        self.tag_func_types().next().is_some()
2061    }
2062
2063    fn tag_func_types(&self) -> impl Iterator<Item = u32> + '_ {
2064        self.func_types
2065            .iter()
2066            .copied()
2067            .filter(move |i| self.func_type(*i).results.is_empty())
2068    }
2069
2070    fn arbitrary_valtype(&self, u: &mut Unstructured) -> Result<ValType> {
2071        #[derive(PartialEq, Eq, PartialOrd, Ord)]
2072        enum ValTypeClass {
2073            I32,
2074            I64,
2075            F32,
2076            F64,
2077            V128,
2078            Ref,
2079        }
2080
2081        let mut val_classes: Vec<_> = self
2082            .valtypes
2083            .iter()
2084            .map(|vt| match vt {
2085                ValType::I32 => ValTypeClass::I32,
2086                ValType::I64 => ValTypeClass::I64,
2087                ValType::F32 => ValTypeClass::F32,
2088                ValType::F64 => ValTypeClass::F64,
2089                ValType::V128 => ValTypeClass::V128,
2090                ValType::Ref(_) => ValTypeClass::Ref,
2091            })
2092            .collect();
2093        val_classes.sort_unstable();
2094        val_classes.dedup();
2095
2096        match u.choose(&val_classes)? {
2097            ValTypeClass::I32 => Ok(ValType::I32),
2098            ValTypeClass::I64 => Ok(ValType::I64),
2099            ValTypeClass::F32 => Ok(ValType::F32),
2100            ValTypeClass::F64 => Ok(ValType::F64),
2101            ValTypeClass::V128 => Ok(ValType::V128),
2102            ValTypeClass::Ref => Ok(ValType::Ref(self.arbitrary_ref_type(u)?)),
2103        }
2104    }
2105
2106    fn arbitrary_global_type(&self, u: &mut Unstructured) -> Result<GlobalType> {
2107        let val_type = self.arbitrary_valtype(u)?;
2108        // Propagate the inner type's sharedness to the global type.
2109        let shared = match val_type {
2110            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {
2111                self.arbitrary_shared(u)?
2112            }
2113            ValType::Ref(r) => self.is_shared_ref_type(r),
2114        };
2115        Ok(GlobalType {
2116            val_type,
2117            mutable: u.arbitrary()?,
2118            shared,
2119        })
2120    }
2121
2122    fn arbitrary_tag_type(&self, u: &mut Unstructured) -> Result<TagType> {
2123        let candidate_func_types: Vec<_> = self.tag_func_types().collect();
2124        arbitrary_tag_type(u, &candidate_func_types, |ty_idx| {
2125            self.func_type(ty_idx).clone()
2126        })
2127    }
2128
2129    fn arbitrary_tags(&mut self, u: &mut Unstructured) -> Result<()> {
2130        if !self.config.exceptions_enabled || !self.has_tag_func_types() {
2131            return Ok(());
2132        }
2133
2134        arbitrary_loop(u, self.config.min_tags, self.config.max_tags, |u| {
2135            if !self.can_add_local_or_import_tag() {
2136                return Ok(false);
2137            }
2138            self.tags.push(self.arbitrary_tag_type(u)?);
2139            self.num_defined_tags += 1;
2140            Ok(true)
2141        })
2142    }
2143
2144    fn arbitrary_funcs(&mut self, u: &mut Unstructured) -> Result<()> {
2145        if self.func_types.is_empty() {
2146            return Ok(());
2147        }
2148
2149        // For now, only define non-shared functions. Until we can update
2150        // instruction generation to understand the additional sharedness
2151        // validation, we don't want to generate instructions that touch
2152        // unshared objects from a shared context (TODO: handle shared).
2153        let unshared_func_types: Vec<_> = self
2154            .func_types
2155            .iter()
2156            .copied()
2157            .filter(|&i| !self.is_shared_type(i))
2158            .collect();
2159        if unshared_func_types.is_empty() {
2160            return Ok(());
2161        }
2162
2163        arbitrary_loop(u, self.config.min_funcs, self.config.max_funcs, |u| {
2164            if !self.can_add_local_or_import_func() {
2165                return Ok(false);
2166            }
2167            let max = unshared_func_types.len() - 1;
2168            let ty = unshared_func_types[u.int_in_range(0..=max)?];
2169            self.funcs.push((ty, self.func_type(ty).clone()));
2170            self.num_defined_funcs += 1;
2171            Ok(true)
2172        })
2173    }
2174
2175    fn arbitrary_tables(&mut self, u: &mut Unstructured) -> Result<()> {
2176        arbitrary_loop(
2177            u,
2178            self.config.min_tables as usize,
2179            self.config.max_tables,
2180            |u| {
2181                if !self.can_add_local_or_import_table() {
2182                    return Ok(false);
2183                }
2184                let ty = arbitrary_table_type(u, self.config(), Some(self))?;
2185                self.add_arbitrary_table_of_type(ty, u)?;
2186                Ok(true)
2187            },
2188        )
2189    }
2190
2191    /// Generates an arbitrary table initialization expression for a table whose
2192    /// element type is `ty`.
2193    ///
2194    /// Table initialization expressions were added by the GC proposal to
2195    /// initialize non-nullable tables.
2196    fn arbitrary_table_init(
2197        &mut self,
2198        u: &mut Unstructured,
2199        ty: RefType,
2200    ) -> Result<Option<ConstExpr>> {
2201        if !self.config.gc_enabled {
2202            assert!(ty.nullable);
2203            return Ok(None);
2204        }
2205        // Even with the GC proposal an initialization expression is not
2206        // required if the element type is nullable.
2207        if ty.nullable && u.arbitrary()? {
2208            return Ok(None);
2209        }
2210        // Only imported globals are allowed in the constant initialization
2211        // expressions for tables.
2212        let expr = self.arbitrary_const_expr(ValType::Ref(ty), u, false)?;
2213        Ok(Some(expr))
2214    }
2215
2216    fn arbitrary_memories(&mut self, u: &mut Unstructured) -> Result<()> {
2217        arbitrary_loop(
2218            u,
2219            self.config.min_memories as usize,
2220            self.config.max_memories,
2221            |u| {
2222                if !self.can_add_local_or_import_memory() {
2223                    return Ok(false);
2224                }
2225                let ty = arbitrary_memtype(u, self.config())?;
2226                self.add_arbitrary_memory_of_type(ty)?;
2227                Ok(true)
2228            },
2229        )
2230    }
2231
2232    /// Add a new global of the given type and return its global index.
2233    fn add_arbitrary_global_of_type(
2234        &mut self,
2235        ty: GlobalType,
2236        u: &mut Unstructured,
2237    ) -> Result<u32> {
2238        let expr = self.arbitrary_const_expr(ty.val_type, u, true)?;
2239        let global_idx = self.globals.len() as u32;
2240        self.globals.push(ty);
2241        self.defined_globals.push((global_idx, expr));
2242        Ok(global_idx)
2243    }
2244
2245    /// Add a new memory of the given type and return its memory index.
2246    fn add_arbitrary_memory_of_type(&mut self, ty: MemoryType) -> Result<u32> {
2247        let memory_idx = self.memories.len() as u32;
2248        self.num_defined_memories += 1;
2249        self.memories.push(ty);
2250        Ok(memory_idx)
2251    }
2252
2253    /// Add a new table of the given type and return its table index.
2254    fn add_arbitrary_table_of_type(&mut self, ty: TableType, u: &mut Unstructured) -> Result<u32> {
2255        let expr = self.arbitrary_table_init(u, ty.element_type)?;
2256        let table_idx = self.tables.len() as u32;
2257        self.tables.push(ty);
2258        self.defined_tables.push(expr);
2259        Ok(table_idx)
2260    }
2261
2262    /// Generates an arbitrary constant expression of the type `ty`.
2263    fn arbitrary_const_expr(
2264        &mut self,
2265        ty: ValType,
2266        u: &mut Unstructured,
2267        allow_defined_globals: bool,
2268    ) -> Result<ConstExpr> {
2269        #[derive(Clone, Copy)]
2270        enum Choice {
2271            GlobalGet(u32),
2272            I32Const,
2273            I64Const,
2274            F32Const,
2275            F64Const,
2276            V128Const,
2277            ExtendedConst,
2278            RefNull(HeapType),
2279            RefFunc(u32),
2280            StructNew(u32),
2281            StructNewDefault(u32),
2282            ArrayNew(u32),
2283            ArrayNewDefault(u32),
2284            ArrayNewFixed(u32),
2285            RefI31 { shared: bool },
2286            AnyConvertExtern { nullable: bool, shared: bool },
2287            ExternConvertAny { nullable: bool, shared: bool },
2288        }
2289
2290        fn encode_instrs(instrs: impl IntoIterator<Item = Instruction>) -> Vec<u8> {
2291            let mut bytes = Vec::new();
2292            for instr in instrs {
2293                instr.encode(&mut bytes);
2294            }
2295            bytes
2296        }
2297
2298        /// Implementation of generation of expressions from the
2299        /// `extended-const` proposal to WebAssembly. This proposal enabled
2300        /// using `i{32,64}.{add,sub,mul}` in constant expressions in addition
2301        /// to the previous `i{32,64}.const` instructions. Note that at this
2302        /// time this doesn't use the full expression generator in
2303        /// `code_builder.rs` but instead inlines just what's necessary for
2304        /// constant expressions here.
2305        fn arbitrary_extended_const(u: &mut Unstructured<'_>, ty: ValType) -> Result<Vec<u8>> {
2306            use wasm_encoder::Instruction::*;
2307
2308            // This only works for i32/i64, would need refactoring for different
2309            // types.
2310            assert!(ty == ValType::I32 || ty == ValType::I64);
2311            let add = if ty == ValType::I32 { I32Add } else { I64Add };
2312            let sub = if ty == ValType::I32 { I32Sub } else { I64Sub };
2313            let mul = if ty == ValType::I32 { I32Mul } else { I64Mul };
2314            let const_: fn(&mut Unstructured<'_>) -> Result<Instruction> = if ty == ValType::I32 {
2315                |u| u.arbitrary().map(I32Const)
2316            } else {
2317                |u| u.arbitrary().map(I64Const)
2318            };
2319
2320            // Here `instrs` is the list of instructions, in reverse order, that
2321            // are going to be emitted. The `needed` value keeps track of how
2322            // many values are needed to complete this expression. New
2323            // instructions must be generated while some more items are needed.
2324            let mut instrs = Vec::new();
2325            let mut needed = 1;
2326            while needed > 0 {
2327                // If fuzz data has been exhausted or if this is a "large
2328                // enough" constant expression then force generation of
2329                // constants to finish out the expression.
2330                let choice = if u.is_empty() || instrs.len() > 10 {
2331                    0
2332                } else {
2333                    u.int_in_range(0..=3)?
2334                };
2335                match choice {
2336                    0 => {
2337                        instrs.push(const_(u)?);
2338                        needed -= 1;
2339                    }
2340                    1 => {
2341                        instrs.push(add.clone());
2342                        needed += 1;
2343                    }
2344                    2 => {
2345                        instrs.push(sub.clone());
2346                        needed += 1;
2347                    }
2348                    3 => {
2349                        instrs.push(mul.clone());
2350                        needed += 1;
2351                    }
2352                    _ => unreachable!(),
2353                }
2354            }
2355            Ok(encode_instrs(instrs.into_iter().rev()))
2356        }
2357
2358        fn abstract_ref(nullable: bool, shared: bool, ty: AbstractHeapType) -> RefType {
2359            RefType::new_abstract(ty, nullable, shared)
2360        }
2361
2362        fn concrete_ref(nullable: bool, ty: u32) -> RefType {
2363            RefType {
2364                nullable,
2365                heap_type: HeapType::Concrete(ty),
2366            }
2367        }
2368
2369        fn type_is_defaultable(field: StorageType) -> bool {
2370            field.unpack().is_defaultable()
2371        }
2372
2373        fn can_use_struct_new(ty: &SubType) -> bool {
2374            ty.composite_type.descriptor.is_none()
2375        }
2376
2377        fn can_use_struct_new_default(ty: &SubType) -> bool {
2378            can_use_struct_new(ty)
2379                && ty
2380                    .unwrap_struct()
2381                    .fields
2382                    .iter()
2383                    .all(|f| type_is_defaultable(f.element_type))
2384        }
2385
2386        fn const_expr_bytes_for_array_length(
2387            module: &mut Module,
2388            u: &mut Unstructured<'_>,
2389            allow_defined_globals: bool,
2390            fuel: &mut u32,
2391        ) -> Result<Vec<u8>> {
2392            if module.config.limit_arrays_in_const_exprs {
2393                let size = u.int_in_range(0..=*fuel)?;
2394                *fuel -= size;
2395                return Ok(encode_instrs([Instruction::I32Const(size as i32)]));
2396            }
2397
2398            const_expr_bytes(module, ValType::I32, u, allow_defined_globals, fuel)
2399        }
2400
2401        fn const_expr_bytes(
2402            module: &mut Module,
2403            ty: ValType,
2404            u: &mut Unstructured<'_>,
2405            allow_defined_globals: bool,
2406            fuel: &mut u32,
2407        ) -> Result<Vec<u8>> {
2408            let mut choices = Vec::new();
2409
2410            for i in module.globals_for_const_expr(ty, allow_defined_globals) {
2411                choices.push(Choice::GlobalGet(i));
2412            }
2413
2414            let ty = match ty {
2415                ValType::Ref(_) => ty,
2416                _ => module.arbitrary_matching_val_type(u, ty)?,
2417            };
2418            match ty {
2419                ValType::I32 => {
2420                    choices.push(Choice::I32Const);
2421                    if module.config.extended_const_enabled {
2422                        choices.push(Choice::ExtendedConst);
2423                    }
2424                }
2425                ValType::I64 => {
2426                    choices.push(Choice::I64Const);
2427                    if module.config.extended_const_enabled {
2428                        choices.push(Choice::ExtendedConst);
2429                    }
2430                }
2431                ValType::F32 => choices.push(Choice::F32Const),
2432                ValType::F64 => choices.push(Choice::F64Const),
2433                ValType::V128 => choices.push(Choice::V128Const),
2434                ValType::Ref(ref_ty) => {
2435                    if ref_ty.nullable {
2436                        choices.push(Choice::RefNull(ref_ty.heap_type));
2437                    }
2438
2439                    for (func_idx, (type_idx, _)) in module.funcs.iter().enumerate() {
2440                        let produced = concrete_ref(false, *type_idx);
2441                        if module.ref_type_is_sub_type(produced, ref_ty) {
2442                            choices.push(Choice::RefFunc(func_idx as u32));
2443                        }
2444                    }
2445
2446                    if module.config.gc_enabled {
2447                        for &type_idx in &module.struct_types {
2448                            let produced = concrete_ref(false, type_idx);
2449                            if !module.ref_type_is_sub_type(produced, ref_ty) {
2450                                continue;
2451                            }
2452                            if can_use_struct_new(module.ty(type_idx))
2453                                && (*fuel > 0
2454                                    || module.ty(type_idx).unwrap_struct().fields.is_empty())
2455                            {
2456                                choices.push(Choice::StructNew(type_idx));
2457                            }
2458                            if can_use_struct_new_default(module.ty(type_idx)) {
2459                                choices.push(Choice::StructNewDefault(type_idx));
2460                            }
2461                        }
2462
2463                        for &type_idx in &module.array_types {
2464                            let produced = concrete_ref(false, type_idx);
2465                            if !module.ref_type_is_sub_type(produced, ref_ty) {
2466                                continue;
2467                            }
2468                            if *fuel > 0 {
2469                                choices.push(Choice::ArrayNew(type_idx));
2470                                choices.push(Choice::ArrayNewFixed(type_idx));
2471                                if type_is_defaultable(
2472                                    module.ty(type_idx).unwrap_array().0.element_type,
2473                                ) {
2474                                    choices.push(Choice::ArrayNewDefault(type_idx));
2475                                }
2476                            }
2477                        }
2478
2479                        let produced_i31 = abstract_ref(false, false, AbstractHeapType::I31);
2480                        if *fuel > 0 && module.ref_type_is_sub_type(produced_i31, ref_ty) {
2481                            choices.push(Choice::RefI31 { shared: false });
2482                        }
2483
2484                        if module.config.shared_everything_threads_enabled {
2485                            let produced_i31 = abstract_ref(false, true, AbstractHeapType::I31);
2486                            if *fuel > 0 && module.ref_type_is_sub_type(produced_i31, ref_ty) {
2487                                choices.push(Choice::RefI31 { shared: true });
2488                            }
2489                        }
2490
2491                        match ref_ty.heap_type {
2492                            HeapType::Abstract {
2493                                shared,
2494                                ty: AbstractHeapType::Any,
2495                            } if *fuel > 0 => {
2496                                choices.push(Choice::AnyConvertExtern {
2497                                    nullable: ref_ty.nullable,
2498                                    shared,
2499                                });
2500                            }
2501                            HeapType::Abstract {
2502                                shared,
2503                                ty: AbstractHeapType::Extern,
2504                            } if *fuel > 0 => {
2505                                choices.push(Choice::ExternConvertAny {
2506                                    nullable: ref_ty.nullable,
2507                                    shared,
2508                                });
2509                            }
2510                            _ => {}
2511                        }
2512                    }
2513                }
2514            }
2515
2516            let choice = *u.choose(&choices)?;
2517            *fuel = fuel.saturating_sub(1);
2518            Ok(match choice {
2519                Choice::GlobalGet(i) => encode_instrs([Instruction::GlobalGet(i)]),
2520                Choice::I32Const => encode_instrs([Instruction::I32Const(u.arbitrary()?)]),
2521                Choice::I64Const => encode_instrs([Instruction::I64Const(u.arbitrary()?)]),
2522                Choice::F32Const => {
2523                    encode_instrs([Instruction::F32Const(u.arbitrary::<f32>()?.into())])
2524                }
2525                Choice::F64Const => {
2526                    encode_instrs([Instruction::F64Const(u.arbitrary::<f64>()?.into())])
2527                }
2528                Choice::V128Const => encode_instrs([Instruction::V128Const(u.arbitrary()?)]),
2529                Choice::ExtendedConst => arbitrary_extended_const(u, ty)?,
2530                Choice::RefNull(heap_type) => encode_instrs([Instruction::RefNull(heap_type)]),
2531                Choice::RefFunc(i) => encode_instrs([Instruction::RefFunc(i)]),
2532                Choice::StructNew(type_idx) => {
2533                    let mut bytes = Vec::new();
2534                    let field_types: Vec<_> = module
2535                        .ty(type_idx)
2536                        .unwrap_struct()
2537                        .fields
2538                        .iter()
2539                        .map(|field| field.element_type.unpack())
2540                        .collect();
2541                    for field_ty in field_types {
2542                        bytes.extend(const_expr_bytes(
2543                            module,
2544                            field_ty,
2545                            u,
2546                            allow_defined_globals,
2547                            fuel,
2548                        )?);
2549                    }
2550                    bytes.extend(encode_instrs([Instruction::StructNew(type_idx)]));
2551                    bytes
2552                }
2553                Choice::StructNewDefault(type_idx) => {
2554                    encode_instrs([Instruction::StructNewDefault(type_idx)])
2555                }
2556                Choice::ArrayNew(type_idx) => {
2557                    let mut bytes = Vec::new();
2558                    let elem_ty = module.ty(type_idx).unwrap_array().0.element_type.unpack();
2559                    bytes.extend(const_expr_bytes(
2560                        module,
2561                        elem_ty,
2562                        u,
2563                        allow_defined_globals,
2564                        fuel,
2565                    )?);
2566                    bytes.extend(const_expr_bytes_for_array_length(
2567                        module,
2568                        u,
2569                        allow_defined_globals,
2570                        fuel,
2571                    )?);
2572                    bytes.extend(encode_instrs([Instruction::ArrayNew(type_idx)]));
2573                    bytes
2574                }
2575                Choice::ArrayNewDefault(type_idx) => {
2576                    let mut bytes =
2577                        const_expr_bytes_for_array_length(module, u, allow_defined_globals, fuel)?;
2578                    bytes.extend(encode_instrs([Instruction::ArrayNewDefault(type_idx)]));
2579                    bytes
2580                }
2581                Choice::ArrayNewFixed(type_idx) => {
2582                    let array_size = u.int_in_range(0..=3)?;
2583                    let array_size = u32::try_from(array_size).unwrap();
2584                    let elem_ty = module.ty(type_idx).unwrap_array().0.element_type.unpack();
2585                    let mut bytes = Vec::new();
2586                    for _ in 0..array_size {
2587                        bytes.extend(const_expr_bytes(
2588                            module,
2589                            elem_ty,
2590                            u,
2591                            allow_defined_globals,
2592                            fuel,
2593                        )?);
2594                    }
2595                    bytes.extend(encode_instrs([Instruction::ArrayNewFixed {
2596                        array_type_index: type_idx,
2597                        array_size,
2598                    }]));
2599                    bytes
2600                }
2601                Choice::RefI31 { shared } => {
2602                    let mut bytes =
2603                        const_expr_bytes(module, ValType::I32, u, allow_defined_globals, fuel)?;
2604                    bytes.extend(encode_instrs([if shared {
2605                        Instruction::RefI31Shared
2606                    } else {
2607                        Instruction::RefI31
2608                    }]));
2609                    bytes
2610                }
2611                Choice::AnyConvertExtern { nullable, shared } => {
2612                    let mut bytes = const_expr_bytes(
2613                        module,
2614                        ValType::Ref(abstract_ref(nullable, shared, AbstractHeapType::Extern)),
2615                        u,
2616                        allow_defined_globals,
2617                        fuel,
2618                    )?;
2619                    bytes.extend(encode_instrs([Instruction::AnyConvertExtern]));
2620                    bytes
2621                }
2622                Choice::ExternConvertAny { nullable, shared } => {
2623                    let mut bytes = const_expr_bytes(
2624                        module,
2625                        ValType::Ref(abstract_ref(nullable, shared, AbstractHeapType::Any)),
2626                        u,
2627                        allow_defined_globals,
2628                        fuel,
2629                    )?;
2630                    bytes.extend(encode_instrs([Instruction::ExternConvertAny]));
2631                    bytes
2632                }
2633            })
2634        }
2635
2636        let mut fuel = self.config.const_expr_fuel;
2637        Ok(ConstExpr::raw(const_expr_bytes(
2638            self,
2639            ty,
2640            u,
2641            allow_defined_globals,
2642            &mut fuel,
2643        )?))
2644    }
2645
2646    fn arbitrary_globals(&mut self, u: &mut Unstructured) -> Result<()> {
2647        arbitrary_loop(u, self.config.min_globals, self.config.max_globals, |u| {
2648            if !self.can_add_local_or_import_global() {
2649                return Ok(false);
2650            }
2651
2652            let ty = self.arbitrary_global_type(u)?;
2653            self.add_arbitrary_global_of_type(ty, u)?;
2654
2655            Ok(true)
2656        })
2657    }
2658
2659    fn required_exports(&mut self, u: &mut Unstructured) -> Result<bool> {
2660        let example_module = if let Some(wasm) = self.config.exports.clone() {
2661            wasm
2662        } else {
2663            return Ok(false);
2664        };
2665
2666        #[cfg(feature = "wasmparser")]
2667        {
2668            self._required_exports(u, &example_module)?;
2669            Ok(true)
2670        }
2671        #[cfg(not(feature = "wasmparser"))]
2672        {
2673            let _ = (example_module, u);
2674            panic!("support for `exports` was disabled at compile time");
2675        }
2676    }
2677
2678    #[cfg(feature = "wasmparser")]
2679    fn _required_exports(&mut self, u: &mut Unstructured, example_module: &[u8]) -> Result<()> {
2680        let mut required_exports: Vec<wasmparser::Export> = vec![];
2681        let mut validator = wasmparser::Validator::new();
2682        let exports_types = validator
2683            .validate_all(&example_module)
2684            .expect("Failed to validate `exports` Wasm");
2685        for payload in wasmparser::Parser::new(0).parse_all(&example_module) {
2686            match payload.expect("Failed to read `exports` Wasm") {
2687                wasmparser::Payload::ExportSection(export_reader) => {
2688                    required_exports = export_reader
2689                        .into_iter()
2690                        .collect::<Result<_, _>>()
2691                        .expect("Failed to read `exports` export section");
2692                }
2693                _ => {}
2694            }
2695        }
2696
2697        // For each export, add necessary prerequisites to the module.
2698        let exports_types = exports_types.as_ref();
2699        let check_and_get_func_type =
2700            |id: wasmparser::types::CoreTypeId| -> (Rc<FuncType>, SubType) {
2701                let subtype = exports_types.get(id).unwrap_or_else(|| {
2702                    panic!("Unable to get subtype for {id:?} in `exports` Wasm")
2703                });
2704                match &subtype.composite_type.inner {
2705                    wasmparser::CompositeInnerType::Func(func_type) => {
2706                        assert!(
2707                            subtype.is_final,
2708                            "Subtype {subtype:?} from `exports` Wasm is not final"
2709                        );
2710                        assert!(
2711                            subtype.supertype_idx.is_none(),
2712                            "Subtype {subtype:?} from `exports` Wasm has non-empty supertype"
2713                        );
2714                        let func_type = Rc::new(FuncType {
2715                            params: func_type
2716                                .params()
2717                                .iter()
2718                                .copied()
2719                                .map(|t| t.try_into().unwrap())
2720                                .collect(),
2721                            results: func_type
2722                                .results()
2723                                .iter()
2724                                .copied()
2725                                .map(|t| t.try_into().unwrap())
2726                                .collect(),
2727                        });
2728                        let subtype = SubType {
2729                            is_final: true,
2730                            supertype: None,
2731                            depth: 1,
2732                            composite_type: CompositeType::new_func(
2733                                Rc::clone(&func_type),
2734                                subtype.composite_type.shared,
2735                            ),
2736                        };
2737                        (func_type, subtype)
2738                    }
2739                    _ => panic!(
2740                        "Unable to handle type {:?} from `exports` Wasm",
2741                        subtype.composite_type
2742                    ),
2743                }
2744            };
2745        for export in required_exports {
2746            let new_index = match exports_types
2747                .entity_type_from_export(&export)
2748                .unwrap_or_else(|| {
2749                    panic!("Unable to get type from export {export:?} in `exports` Wasm",)
2750                }) {
2751                // For functions, add the type and a function with that type.
2752                wasmparser::types::EntityType::Func(id) => {
2753                    let (func_type, subtype) = check_and_get_func_type(id);
2754                    self.rec_groups.push(self.types.len()..self.types.len() + 1);
2755                    let type_index = self.add_type(subtype);
2756                    let func_index = self.funcs.len() as u32;
2757                    self.funcs.push((type_index, func_type));
2758                    self.num_defined_funcs += 1;
2759                    func_index
2760                }
2761                // For globals, add a new global.
2762                wasmparser::types::EntityType::Global(global_type) => {
2763                    self.add_arbitrary_global_of_type(global_type.try_into().unwrap(), u)?
2764                }
2765                // For memories, add a new memory.
2766                wasmparser::types::EntityType::Memory(memory_type) => {
2767                    self.add_arbitrary_memory_of_type(memory_type.into())?
2768                }
2769                // For tables, add a new table.
2770                wasmparser::types::EntityType::Table(table_type) => {
2771                    self.add_arbitrary_table_of_type(table_type.try_into().unwrap(), u)?
2772                }
2773                // For tags, add the type.
2774                wasmparser::types::EntityType::Tag(id) => {
2775                    let (func_type, subtype) = check_and_get_func_type(id);
2776                    self.rec_groups.push(self.types.len()..self.types.len() + 1);
2777                    let type_index = self.add_type(subtype);
2778                    let tag_index = self.tags.len() as u32;
2779                    self.tags.push(TagType {
2780                        func_type_idx: type_index,
2781                        func_type: func_type,
2782                    });
2783                    self.num_defined_tags += 1;
2784                    tag_index
2785                }
2786                wasmparser::types::EntityType::FuncExact(_) => {
2787                    panic!("Unexpected func_export: {export:?}",);
2788                }
2789            };
2790            self.exports
2791                .push((export.name.to_string(), export.kind.into(), new_index));
2792            self.export_names.insert(export.name.to_string());
2793        }
2794
2795        Ok(())
2796    }
2797
2798    fn arbitrary_exports(&mut self, u: &mut Unstructured) -> Result<()> {
2799        if self.config.max_type_size < self.type_size && !self.config.export_everything {
2800            return Ok(());
2801        }
2802
2803        // Build up a list of candidates for each class of import
2804        let mut choices: Vec<Vec<(ExportKind, u32)>> = Vec::with_capacity(6);
2805        choices.push(
2806            (0..self.funcs.len())
2807                .map(|i| (ExportKind::Func, i as u32))
2808                .collect(),
2809        );
2810        choices.push(
2811            (0..self.tables.len())
2812                .map(|i| (ExportKind::Table, i as u32))
2813                .collect(),
2814        );
2815        choices.push(
2816            (0..self.memories.len())
2817                .map(|i| (ExportKind::Memory, i as u32))
2818                .collect(),
2819        );
2820        choices.push(
2821            (0..self.globals.len())
2822                .map(|i| (ExportKind::Global, i as u32))
2823                .collect(),
2824        );
2825
2826        // If the configuration demands exporting everything, we do so here and
2827        // early-return.
2828        if self.config.export_everything {
2829            for choices_by_kind in choices {
2830                for (kind, idx) in choices_by_kind {
2831                    let name = unique_string(1_000, &mut self.export_names, u)?;
2832                    self.add_arbitrary_export(name, kind, idx)?;
2833                }
2834            }
2835            return Ok(());
2836        }
2837
2838        arbitrary_loop(u, self.config.min_exports, self.config.max_exports, |u| {
2839            // Remove all candidates for export whose type size exceeds our
2840            // remaining budget for type size. Then also remove any classes
2841            // of exports which no longer have any candidates.
2842            //
2843            // If there's nothing remaining after this, then we're done.
2844            let max_size = self.config.max_type_size - self.type_size;
2845            for list in choices.iter_mut() {
2846                list.retain(|(kind, idx)| self.type_of(*kind, *idx).size() + 1 < max_size);
2847            }
2848            choices.retain(|list| !list.is_empty());
2849            if choices.is_empty() {
2850                return Ok(false);
2851            }
2852
2853            // Pick a name, then pick the export, and then we can record
2854            // information about the chosen export.
2855            let name = unique_string(1_000, &mut self.export_names, u)?;
2856            let list = u.choose(&choices)?;
2857            let (kind, idx) = *u.choose(list)?;
2858            self.add_arbitrary_export(name, kind, idx)?;
2859            Ok(true)
2860        })
2861    }
2862
2863    fn add_arbitrary_export(&mut self, name: String, kind: ExportKind, idx: u32) -> Result<()> {
2864        let ty = self.type_of(kind, idx);
2865        self.type_size += 1 + ty.size();
2866        if self.type_size <= self.config.max_type_size {
2867            self.exports.push((name, kind, idx));
2868            Ok(())
2869        } else {
2870            // If our addition of exports takes us above the allowed number of
2871            // types, we fail; this error code is not the most illustrative of
2872            // the cause but is the best available from `arbitrary`.
2873            Err(arbitrary::Error::IncorrectFormat)
2874        }
2875    }
2876
2877    fn arbitrary_start(&mut self, u: &mut Unstructured) -> Result<()> {
2878        if !self.config.allow_start_export {
2879            return Ok(());
2880        }
2881
2882        let mut choices = Vec::with_capacity(self.funcs.len());
2883
2884        for (func_idx, ty) in self.funcs() {
2885            if ty.params.is_empty() && ty.results.is_empty() {
2886                choices.push(func_idx);
2887            }
2888        }
2889
2890        if !choices.is_empty() && u.arbitrary().unwrap_or(false) {
2891            let f = *u.choose(&choices)?;
2892            self.start = Some(f);
2893        }
2894
2895        Ok(())
2896    }
2897
2898    fn arbitrary_elems(&mut self, u: &mut Unstructured) -> Result<()> {
2899        // Create a helper closure to choose an arbitrary offset.
2900        let mut global_i32 = vec![];
2901        let mut global_i64 = vec![];
2902        if !self.config.disallow_traps {
2903            for i in self.globals_for_const_expr(ValType::I32, true) {
2904                global_i32.push(i);
2905            }
2906            for i in self.globals_for_const_expr(ValType::I64, true) {
2907                global_i64.push(i);
2908            }
2909        }
2910        let disallow_traps = self.config.disallow_traps;
2911        let arbitrary_active_elem =
2912            |u: &mut Unstructured, min_mem_size: u64, table: Option<u32>, table_ty: &TableType| {
2913                let global_choices = if table_ty.table64 {
2914                    &global_i64
2915                } else {
2916                    &global_i32
2917                };
2918                let (offset, max_size_hint) = if !global_choices.is_empty() && u.arbitrary()? {
2919                    let g = u.choose(&global_choices)?;
2920                    (Offset::Global(*g), None)
2921                } else {
2922                    let max_mem_size = if disallow_traps {
2923                        table_ty.minimum
2924                    } else if table_ty.table64 {
2925                        u64::MAX
2926                    } else {
2927                        u64::from(u32::MAX)
2928                    };
2929                    let offset = arbitrary_offset(u, min_mem_size, max_mem_size, 0)?;
2930                    let max_size_hint = if disallow_traps
2931                        || (offset <= min_mem_size
2932                            && u.int_in_range(0..=CHANCE_OFFSET_INBOUNDS)? != 0)
2933                    {
2934                        Some(min_mem_size - offset)
2935                    } else {
2936                        None
2937                    };
2938
2939                    let offset = if table_ty.table64 {
2940                        Offset::Const64(offset as i64)
2941                    } else {
2942                        Offset::Const32(offset as i32)
2943                    };
2944                    (offset, max_size_hint)
2945                };
2946                Ok((ElementKind::Active { table, offset }, max_size_hint))
2947            };
2948
2949        // Generate a list of candidates for "kinds" of elements segments. For
2950        // example we can have an active segment for any existing table or
2951        // passive/declared segments if the right wasm features are enabled.
2952        type GenElemSegment<'a> =
2953            dyn Fn(&mut Unstructured) -> Result<(ElementKind, Option<u64>)> + 'a;
2954        let mut choices: Vec<Box<GenElemSegment>> = Vec::new();
2955
2956        // Bulk memory enables passive/declared segments, and note that the
2957        // types used are selected later.
2958        if self.config.bulk_memory_enabled {
2959            choices.push(Box::new(|_| Ok((ElementKind::Passive, None))));
2960            choices.push(Box::new(|_| Ok((ElementKind::Declared, None))));
2961        }
2962
2963        for (i, ty) in self.tables.iter().enumerate() {
2964            // If this table starts with no capacity then any non-empty element
2965            // segment placed onto it will immediately trap, which isn't too
2966            // too interesting. If that's the case give it an unlikely chance
2967            // of proceeding.
2968            if ty.minimum == 0 && u.int_in_range(0..=CHANCE_SEGMENT_ON_EMPTY)? != 0 {
2969                continue;
2970            }
2971
2972            let minimum = ty.minimum;
2973            // If the first table is a funcref table then it's a candidate for
2974            // the MVP encoding of element segments.
2975            let ty = *ty;
2976            if i == 0 && ty.element_type == RefType::FUNCREF {
2977                choices.push(Box::new(move |u| {
2978                    arbitrary_active_elem(u, minimum, None, &ty)
2979                }));
2980            }
2981            if self.config.bulk_memory_enabled {
2982                let idx = Some(i as u32);
2983                choices.push(Box::new(move |u| {
2984                    arbitrary_active_elem(u, minimum, idx, &ty)
2985                }));
2986            }
2987        }
2988
2989        if choices.is_empty() {
2990            return Ok(());
2991        }
2992
2993        let mut total_elements = 0_usize;
2994
2995        arbitrary_loop(
2996            u,
2997            self.config.min_element_segments,
2998            self.config.max_element_segments,
2999            |u| {
3000                // Pick a kind of element segment to generate which will also
3001                // give us a hint of the maximum size, if any.
3002                let (kind, max_size_hint) = u.choose(&choices)?(u)?;
3003                let max = max_size_hint
3004                    .map(|i| usize::try_from(i).unwrap())
3005                    .unwrap_or(self.config.max_elements);
3006
3007                // Infer, from the kind of segment, the type of the element
3008                // segment. Passive/declared segments can be declared with any
3009                // reference type, but active segments must match their table.
3010                let ty = match kind {
3011                    ElementKind::Passive | ElementKind::Declared => self.arbitrary_ref_type(u)?,
3012                    ElementKind::Active { table, .. } => {
3013                        let idx = table.unwrap_or(0);
3014                        self.arbitrary_matching_ref_type(u, self.tables[idx as usize].element_type)?
3015                    }
3016                };
3017
3018                // The `Elements::Functions` encoding is only possible when the
3019                // element type is a `funcref` because the binary format can't
3020                // allow encoding any other type in that form.
3021                let can_use_function_list = ty == RefType::FUNCREF;
3022                if !self.config.reference_types_enabled {
3023                    assert!(can_use_function_list);
3024                }
3025
3026                // If a function list is possible then build up a list of
3027                // functions that can be selected from.
3028                let mut func_candidates = Vec::new();
3029                if can_use_function_list {
3030                    match ty.heap_type {
3031                        HeapType::Abstract {
3032                            ty: AbstractHeapType::Func,
3033                            ..
3034                        } => {
3035                            func_candidates.extend(0..self.funcs.len() as u32);
3036                        }
3037                        HeapType::Concrete(ty) => {
3038                            for (i, (fty, _)) in self.funcs.iter().enumerate() {
3039                                if *fty == ty {
3040                                    func_candidates.push(i as u32);
3041                                }
3042                            }
3043                        }
3044                        _ => {}
3045                    }
3046                }
3047
3048                // Clamp the max elements for this segment based on the
3049                // configuration's maximum number of elements for the entire
3050                // module minus what we've generated so far.
3051                let max = (total_elements.saturating_sub(self.config.max_elements)).min(max);
3052
3053                // And finally actually generate the arbitrary elements of this
3054                // element segment. Function indices are used if they're either
3055                // forced or allowed, and otherwise expressions are used
3056                // instead.
3057                let items = if !self.config.reference_types_enabled
3058                    || (can_use_function_list && u.arbitrary()?)
3059                {
3060                    let mut init = vec![];
3061                    if func_candidates.len() > 0 {
3062                        arbitrary_loop(u, self.config.min_elements, max, |u| {
3063                            let func_idx = *u.choose(&func_candidates)?;
3064                            init.push(func_idx);
3065                            Ok(true)
3066                        })?;
3067                    }
3068                    total_elements += init.len();
3069                    Elements::Functions(init)
3070                } else {
3071                    let mut init = vec![];
3072                    arbitrary_loop(u, self.config.min_elements, max, |u| {
3073                        init.push(self.arbitrary_const_expr(ValType::Ref(ty), u, true)?);
3074                        Ok(true)
3075                    })?;
3076                    total_elements += init.len();
3077                    Elements::Expressions(init)
3078                };
3079
3080                self.elems.push(ElementSegment { kind, ty, items });
3081                Ok(true)
3082            },
3083        )
3084    }
3085
3086    fn arbitrary_code(&mut self, u: &mut Unstructured) -> Result<()> {
3087        self.compute_interesting_values();
3088
3089        self.code.reserve(self.num_defined_funcs);
3090        let mut allocs = CodeBuilderAllocations::new(
3091            self,
3092            self.config.exports.is_some() || self.config.module_shape.is_some(),
3093        );
3094        for (idx, ty) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() {
3095            let shared = self.is_shared_type(*idx);
3096            let body = self.arbitrary_func_body(u, ty, &mut allocs, shared)?;
3097            self.code.push(body);
3098        }
3099        allocs.finish(u, self)?;
3100        Ok(())
3101    }
3102
3103    fn arbitrary_func_body(
3104        &self,
3105        u: &mut Unstructured,
3106        ty: &FuncType,
3107        allocs: &mut CodeBuilderAllocations,
3108        shared: bool,
3109    ) -> Result<Code> {
3110        let mut locals = self.arbitrary_locals(u)?;
3111        let builder = allocs.builder(ty, &mut locals, shared);
3112        let instructions = if self.config.allow_invalid_funcs && u.arbitrary().unwrap_or(false) {
3113            Instructions::Arbitrary(arbitrary_vec_u8(u)?)
3114        } else {
3115            Instructions::Generated(builder.arbitrary(u, self)?)
3116        };
3117
3118        Ok(Code {
3119            locals,
3120            instructions,
3121        })
3122    }
3123
3124    fn arbitrary_locals(&self, u: &mut Unstructured) -> Result<Vec<ValType>> {
3125        let mut ret = Vec::new();
3126        arbitrary_loop(u, 0, 100, |u| {
3127            ret.push(self.arbitrary_valtype(u)?);
3128            Ok(true)
3129        })?;
3130        Ok(ret)
3131    }
3132
3133    fn arbitrary_data(&mut self, u: &mut Unstructured) -> Result<()> {
3134        // With bulk-memory we can generate passive data, otherwise if there are
3135        // no memories we can't generate any data.
3136        let memories = self.memories.len() as u32;
3137        if memories == 0 && !self.config.bulk_memory_enabled {
3138            return Ok(());
3139        }
3140        let disallow_traps = self.config.disallow_traps;
3141        let mut choices32: Vec<
3142            Box<dyn Fn(&mut Unstructured, &MemoryType, usize) -> Result<Offset>>,
3143        > = vec![];
3144        fn min(ty: &MemoryType) -> u64 {
3145            ty.minimum.saturating_mul(u64::from(ty.page_size()))
3146        }
3147        choices32.push(Box::new(|u, ty, data_len| {
3148            let min = u32::try_from(min(ty)).unwrap_or(u32::MAX).into();
3149            let max = if disallow_traps { min } else { u32::MAX.into() };
3150            Ok(Offset::Const32(
3151                arbitrary_offset(u, min, max, data_len)? as i32
3152            ))
3153        }));
3154        let mut choices64: Vec<
3155            Box<dyn Fn(&mut Unstructured, &MemoryType, usize) -> Result<Offset>>,
3156        > = vec![];
3157        choices64.push(Box::new(|u, ty, data_len| {
3158            let min = min(ty);
3159            let max = if disallow_traps { min } else { u64::MAX };
3160            Ok(Offset::Const64(
3161                arbitrary_offset(u, min, max, data_len)? as i64
3162            ))
3163        }));
3164        if !self.config.disallow_traps {
3165            for i in self.globals_for_const_expr(ValType::I32, true) {
3166                choices32.push(Box::new(move |_, _, _| Ok(Offset::Global(i))));
3167            }
3168            for i in self.globals_for_const_expr(ValType::I64, true) {
3169                choices64.push(Box::new(move |_, _, _| Ok(Offset::Global(i))));
3170            }
3171        }
3172
3173        // Build a list of candidate memories that we'll add data initializers
3174        // for. If a memory doesn't have an initial size then any initializers
3175        // for that memory will trap instantiation, which isn't too
3176        // interesting. Try to make this happen less often by making it less
3177        // likely that a memory with 0 size will have a data segment.
3178        let mut memories = Vec::new();
3179        for (i, mem) in self.memories.iter().enumerate() {
3180            if mem.minimum > 0 || u.int_in_range(0..=CHANCE_SEGMENT_ON_EMPTY)? == 0 {
3181                memories.push(i as u32);
3182            }
3183        }
3184
3185        // With memories we can generate data segments, and with bulk memory we
3186        // can generate passive segments. Without these though we can't create
3187        // a valid module with data segments.
3188        if memories.is_empty() && !self.config.bulk_memory_enabled {
3189            return Ok(());
3190        }
3191
3192        arbitrary_loop(
3193            u,
3194            self.config.min_data_segments,
3195            self.config.max_data_segments,
3196            |u| {
3197                let mut init: Vec<u8> = u.arbitrary()?;
3198
3199                // Passive data can only be generated if bulk memory is enabled.
3200                // Otherwise if there are no memories we *only* generate passive
3201                // data. Finally if all conditions are met we use an input byte to
3202                // determine if it should be passive or active.
3203                let kind =
3204                    if self.config.bulk_memory_enabled && (memories.is_empty() || u.arbitrary()?) {
3205                        DataSegmentKind::Passive
3206                    } else {
3207                        let memory_index = *u.choose(&memories)?;
3208                        let mem = &self.memories[memory_index as usize];
3209                        let f = if mem.memory64 {
3210                            u.choose(&choices64)?
3211                        } else {
3212                            u.choose(&choices32)?
3213                        };
3214                        let mut offset = f(u, mem, init.len())?;
3215
3216                        // If traps are disallowed then truncate the size of the
3217                        // data segment to the minimum size of memory to guarantee
3218                        // it will fit. Afterwards ensure that the offset of the
3219                        // data segment is in-bounds by clamping it to the
3220                        if self.config.disallow_traps {
3221                            let page_size = u64::from(mem.page_size());
3222                            let max_size = (u64::MAX / page_size).min(mem.minimum) * page_size;
3223                            init.truncate(max_size as usize);
3224                            let max_offset = max_size - init.len() as u64;
3225                            match &mut offset {
3226                                Offset::Const32(x) => {
3227                                    *x = (*x as u64).min(max_offset) as i32;
3228                                }
3229                                Offset::Const64(x) => {
3230                                    *x = (*x as u64).min(max_offset) as i64;
3231                                }
3232                                Offset::Global(_) => unreachable!(),
3233                            }
3234                        }
3235                        DataSegmentKind::Active {
3236                            offset,
3237                            memory_index,
3238                        }
3239                    };
3240                self.data.push(DataSegment { kind, init });
3241                Ok(true)
3242            },
3243        )
3244    }
3245
3246    fn params_results(&self, ty: &BlockType) -> (Vec<ValType>, Vec<ValType>) {
3247        match ty {
3248            BlockType::Empty => (vec![], vec![]),
3249            BlockType::Result(t) => (vec![], vec![*t]),
3250            BlockType::FunctionType(ty) => {
3251                let ty = self.func_type(*ty);
3252                (ty.params.to_vec(), ty.results.to_vec())
3253            }
3254        }
3255    }
3256
3257    /// Returns an iterator of all globals which can be used in constant
3258    /// expressions for a value of type `ty` specified.
3259    fn globals_for_const_expr(
3260        &self,
3261        ty: ValType,
3262        allow_defined_globals: bool,
3263    ) -> impl Iterator<Item = u32> + '_ {
3264        // Before the GC proposal only imported globals could be referenced, but
3265        // the GC proposal relaxed this feature to allow any global.
3266        let num_imported_globals = self.globals.len() - self.defined_globals.len();
3267        let max_global = if self.config.gc_enabled && allow_defined_globals {
3268            self.globals.len()
3269        } else {
3270            num_imported_globals
3271        };
3272
3273        self.globals[..max_global]
3274            .iter()
3275            .enumerate()
3276            .filter_map(move |(i, g)| {
3277                // Mutable globals cannot participate in constant expressions,
3278                // but otherwise so long as the global is a subtype of the
3279                // desired type it's a candidate.
3280                if !g.mutable && self.val_type_is_sub_type(g.val_type, ty) {
3281                    Some(i as u32)
3282                } else {
3283                    None
3284                }
3285            })
3286    }
3287
3288    fn compute_interesting_values(&mut self) {
3289        debug_assert!(self.interesting_values32.is_empty());
3290        debug_assert!(self.interesting_values64.is_empty());
3291
3292        let mut interesting_values32 = HashSet::new();
3293        let mut interesting_values64 = HashSet::new();
3294
3295        let mut interesting = |val: u64| {
3296            interesting_values32.insert(val as u32);
3297            interesting_values64.insert(val);
3298        };
3299
3300        // Zero is always interesting.
3301        interesting(0);
3302
3303        // Max values are always interesting.
3304        interesting(u8::MAX as _);
3305        interesting(u16::MAX as _);
3306        interesting(u32::MAX as _);
3307        interesting(u64::MAX);
3308
3309        // Min values are always interesting.
3310        interesting(i8::MIN as _);
3311        interesting(i16::MIN as _);
3312        interesting(i32::MIN as _);
3313        interesting(i64::MIN as _);
3314
3315        for i in 0..64 {
3316            // Powers of two.
3317            interesting(1 << i);
3318
3319            // Inverted powers of two.
3320            interesting(!(1 << i));
3321
3322            // Powers of two minus one, AKA high bits unset and low bits set.
3323            interesting((1 << i) - 1);
3324
3325            // Negative powers of two, AKA high bits set and low bits unset.
3326            interesting(((1_i64 << 63) >> i) as _);
3327        }
3328
3329        // Some repeating bit patterns.
3330        for pattern in [0b01010101, 0b00010001, 0b00010001, 0b00000001] {
3331            for b in [pattern, !pattern] {
3332                interesting(u64::from_ne_bytes([b, b, b, b, b, b, b, b]));
3333            }
3334        }
3335
3336        // Interesting float values.
3337        let mut interesting_f64 = |x: f64| interesting(x.to_bits());
3338        interesting_f64(0.0);
3339        interesting_f64(-0.0);
3340        interesting_f64(f64::INFINITY);
3341        interesting_f64(f64::NEG_INFINITY);
3342        interesting_f64(f64::EPSILON);
3343        interesting_f64(-f64::EPSILON);
3344        interesting_f64(f64::MIN);
3345        interesting_f64(f64::MIN_POSITIVE);
3346        interesting_f64(f64::MAX);
3347        interesting_f64(f64::NAN);
3348        let mut interesting_f32 = |x: f32| interesting(x.to_bits() as _);
3349        interesting_f32(0.0);
3350        interesting_f32(-0.0);
3351        interesting_f32(f32::INFINITY);
3352        interesting_f32(f32::NEG_INFINITY);
3353        interesting_f32(f32::EPSILON);
3354        interesting_f32(-f32::EPSILON);
3355        interesting_f32(f32::MIN);
3356        interesting_f32(f32::MIN_POSITIVE);
3357        interesting_f32(f32::MAX);
3358        interesting_f32(f32::NAN);
3359
3360        // Interesting values related to table bounds.
3361        for t in self.tables.iter() {
3362            interesting(t.minimum as _);
3363            if let Some(x) = t.minimum.checked_add(1) {
3364                interesting(x as _);
3365            }
3366
3367            if let Some(x) = t.maximum {
3368                interesting(x as _);
3369                if let Some(y) = x.checked_add(1) {
3370                    interesting(y as _);
3371                }
3372            }
3373        }
3374
3375        // Interesting values related to memory bounds.
3376        for m in self.memories.iter() {
3377            let min = m.minimum.saturating_mul(m.page_size().into());
3378            interesting(min);
3379            for i in 0..5 {
3380                if let Some(x) = min.checked_add(1 << i) {
3381                    interesting(x);
3382                }
3383                if let Some(x) = min.checked_sub(1 << i) {
3384                    interesting(x);
3385                }
3386            }
3387
3388            if let Some(max) = m.maximum {
3389                let max = max.saturating_mul(m.page_size().into());
3390                interesting(max);
3391                for i in 0..5 {
3392                    if let Some(x) = max.checked_add(1 << i) {
3393                        interesting(x);
3394                    }
3395                    if let Some(x) = max.checked_sub(1 << i) {
3396                        interesting(x);
3397                    }
3398                }
3399            }
3400        }
3401
3402        self.interesting_values32.extend(interesting_values32);
3403        self.interesting_values64.extend(interesting_values64);
3404
3405        // Sort for determinism.
3406        self.interesting_values32.sort();
3407        self.interesting_values64.sort();
3408    }
3409
3410    fn arbitrary_const_instruction(
3411        &self,
3412        ty: ValType,
3413        u: &mut Unstructured<'_>,
3414    ) -> Result<Instruction> {
3415        debug_assert!(self.interesting_values32.len() > 0);
3416        debug_assert!(self.interesting_values64.len() > 0);
3417        match ty {
3418            ValType::I32 => Ok(Instruction::I32Const(if u.arbitrary()? {
3419                *u.choose(&self.interesting_values32)? as i32
3420            } else {
3421                u.arbitrary()?
3422            })),
3423            ValType::I64 => Ok(Instruction::I64Const(if u.arbitrary()? {
3424                *u.choose(&self.interesting_values64)? as i64
3425            } else {
3426                u.arbitrary()?
3427            })),
3428            ValType::F32 => Ok(Instruction::F32Const(if u.arbitrary()? {
3429                f32::from_bits(*u.choose(&self.interesting_values32)?).into()
3430            } else {
3431                u.arbitrary::<f32>()?.into()
3432            })),
3433            ValType::F64 => Ok(Instruction::F64Const(if u.arbitrary()? {
3434                f64::from_bits(*u.choose(&self.interesting_values64)?).into()
3435            } else {
3436                u.arbitrary::<f64>()?.into()
3437            })),
3438            ValType::V128 => Ok(Instruction::V128Const(if u.arbitrary()? {
3439                let upper = (*u.choose(&self.interesting_values64)? as i128) << 64;
3440                let lower = *u.choose(&self.interesting_values64)? as i128;
3441                upper | lower
3442            } else {
3443                u.arbitrary()?
3444            })),
3445            ValType::Ref(ty) => {
3446                assert!(ty.nullable);
3447                Ok(Instruction::RefNull(ty.heap_type))
3448            }
3449        }
3450    }
3451
3452    fn propagate_shared<T>(&mut self, must_share: bool, mut f: impl FnMut(&mut Self) -> T) -> T {
3453        let tmp = mem::replace(&mut self.must_share, must_share);
3454        let result = f(self);
3455        self.must_share = tmp;
3456        result
3457    }
3458
3459    fn arbitrary_shared(&self, u: &mut Unstructured) -> Result<bool> {
3460        if self.must_share {
3461            Ok(true)
3462        } else {
3463            Ok(self.config.shared_everything_threads_enabled && u.ratio(1, 4)?)
3464        }
3465    }
3466
3467    fn is_shared_ref_type(&self, ty: RefType) -> bool {
3468        match ty.heap_type {
3469            HeapType::Abstract { shared, .. } => shared,
3470            HeapType::Concrete(i) | HeapType::Exact(i) => {
3471                self.types[i as usize].composite_type.shared
3472            }
3473        }
3474    }
3475
3476    fn is_shared_type(&self, index: u32) -> bool {
3477        let index = usize::try_from(index).unwrap();
3478        let ty = self.types.get(index).unwrap();
3479        ty.composite_type.shared
3480    }
3481}
3482
3483pub(crate) fn arbitrary_limits64(
3484    u: &mut Unstructured,
3485    min_minimum: Option<u64>,
3486    max_minimum: u64,
3487    max_required: bool,
3488    max_inbounds: u64,
3489) -> Result<(u64, Option<u64>)> {
3490    assert!(
3491        min_minimum.unwrap_or(0) <= max_minimum,
3492        "{} <= {max_minimum}",
3493        min_minimum.unwrap_or(0),
3494    );
3495    assert!(
3496        min_minimum.unwrap_or(0) <= max_inbounds,
3497        "{} <= {max_inbounds}",
3498        min_minimum.unwrap_or(0),
3499    );
3500
3501    let min = gradually_grow(u, min_minimum.unwrap_or(0), max_inbounds, max_minimum)?;
3502    assert!(min <= max_minimum, "{min} <= {max_minimum}");
3503
3504    let max = if max_required || u.arbitrary().unwrap_or(false) {
3505        Some(u.int_in_range(min..=max_minimum)?)
3506    } else {
3507        None
3508    };
3509    assert!(min <= max.unwrap_or(min), "{min} <= {}", max.unwrap_or(min));
3510
3511    Ok((min, max))
3512}
3513
3514pub(crate) fn configured_valtypes(config: &Config) -> Vec<ValType> {
3515    let mut valtypes = Vec::with_capacity(25);
3516    valtypes.push(ValType::I32);
3517    valtypes.push(ValType::I64);
3518    if config.allow_floats {
3519        valtypes.push(ValType::F32);
3520        valtypes.push(ValType::F64);
3521    }
3522    if config.simd_enabled {
3523        valtypes.push(ValType::V128);
3524    }
3525    if config.gc_enabled && config.reference_types_enabled {
3526        for nullable in [
3527            // TODO: For now, only create allow nullable reference
3528            // types. Eventually we should support non-nullable reference types,
3529            // but this means that we will also need to recognize when it is
3530            // impossible to create an instance of the reference (eg `(ref
3531            // nofunc)` has no instances, and self-referential types that
3532            // contain a non-null self-reference are also impossible to create).
3533            true,
3534        ] {
3535            use AbstractHeapType::*;
3536            let abs_ref_types = [
3537                Any, Eq, I31, Array, Struct, None, Func, NoFunc, Extern, NoExtern,
3538            ];
3539            valtypes.extend(
3540                abs_ref_types
3541                    .iter()
3542                    .map(|&ty| ValType::Ref(RefType::new_abstract(ty, nullable, false))),
3543            );
3544            if config.shared_everything_threads_enabled {
3545                valtypes.extend(
3546                    abs_ref_types
3547                        .iter()
3548                        .map(|&ty| ValType::Ref(RefType::new_abstract(ty, nullable, true))),
3549                );
3550            }
3551        }
3552    } else if config.reference_types_enabled {
3553        valtypes.push(ValType::EXTERNREF);
3554        valtypes.push(ValType::FUNCREF);
3555    }
3556    valtypes
3557}
3558
3559pub(crate) fn arbitrary_table_type(
3560    u: &mut Unstructured,
3561    config: &Config,
3562    module: Option<&Module>,
3563) -> Result<TableType> {
3564    let table64 = config.memory64_enabled && u.arbitrary()?;
3565    // We don't want to generate tables that are too large on average, so
3566    // keep the "inbounds" limit here a bit smaller.
3567    let max_inbounds = 10_000;
3568    let min_elements = if config.disallow_traps { Some(1) } else { None };
3569    let mut max_elements = min_elements.unwrap_or(0).max(config.max_table_elements);
3570    // Further limit by the table's type if necessary.
3571    if !table64 {
3572        max_elements = max_elements.min(u64::from(u32::MAX));
3573    }
3574    let (minimum, maximum) = arbitrary_limits64(
3575        u,
3576        min_elements,
3577        max_elements,
3578        config.table_max_size_required,
3579        max_inbounds.min(max_elements),
3580    )?;
3581    if config.disallow_traps {
3582        assert!(minimum > 0);
3583    }
3584    let element_type = match module {
3585        Some(module) => module.arbitrary_ref_type(u)?,
3586        None => RefType::FUNCREF,
3587    };
3588
3589    // Propagate the element type's sharedness to the table type.
3590    let shared = match module {
3591        Some(module) => module.is_shared_ref_type(element_type),
3592        None => false,
3593    };
3594
3595    Ok(TableType {
3596        element_type,
3597        minimum,
3598        maximum,
3599        table64,
3600        shared,
3601    })
3602}
3603
3604pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result<MemoryType> {
3605    // When threads are enabled, we only want to generate shared memories about
3606    // 25% of the time.
3607    let shared = config.threads_enabled && u.ratio(1, 4)?;
3608
3609    let memory64 = config.memory64_enabled && u.arbitrary()?;
3610    let page_size_log2 = if config.custom_page_sizes_enabled && u.arbitrary()? {
3611        Some(if u.arbitrary()? { 0 } else { 16 })
3612    } else {
3613        None
3614    };
3615
3616    let min_pages = if config.disallow_traps { Some(1) } else { None };
3617    let max_pages = min_pages.unwrap_or(0).max(if memory64 {
3618        u64::try_from(config.max_memory64_bytes >> page_size_log2.unwrap_or(16))
3619            // Can only fail when we have a custom page size of 1 byte and a
3620            // memory size of `2**64 == u64::MAX + 1`. In this case, just
3621            // saturate to `u64::MAX`.
3622            .unwrap_or(u64::MAX)
3623    } else {
3624        u32::try_from(config.max_memory32_bytes >> page_size_log2.unwrap_or(16))
3625            // Similar case as above, but while we could represent `2**32` in our
3626            // `u64` here, 32-bit memories' limits must fit in a `u32`.
3627            .unwrap_or(u32::MAX)
3628            .into()
3629    });
3630
3631    // We want to favor keeping the total memories <= 1gb in size.
3632    let max_all_mems_in_bytes = 1 << 30;
3633    let max_this_mem_in_bytes = max_all_mems_in_bytes / u64::try_from(config.max_memories).unwrap();
3634    let max_inbounds = max_this_mem_in_bytes >> page_size_log2.unwrap_or(16);
3635    let max_inbounds = max_inbounds.clamp(min_pages.unwrap_or(0), max_pages);
3636
3637    let (minimum, maximum) = arbitrary_limits64(
3638        u,
3639        min_pages,
3640        max_pages,
3641        config.memory_max_size_required || shared,
3642        max_inbounds,
3643    )?;
3644
3645    Ok(MemoryType {
3646        minimum,
3647        maximum,
3648        memory64,
3649        shared,
3650        page_size_log2,
3651    })
3652}
3653
3654pub(crate) fn arbitrary_tag_type(
3655    u: &mut Unstructured,
3656    candidate_func_types: &[u32],
3657    get_func_type: impl FnOnce(u32) -> Rc<FuncType>,
3658) -> Result<TagType> {
3659    let max = candidate_func_types.len() - 1;
3660    let ty = candidate_func_types[u.int_in_range(0..=max)?];
3661    Ok(TagType {
3662        func_type_idx: ty,
3663        func_type: get_func_type(ty),
3664    })
3665}
3666
3667/// This function generates a number between `min` and `max`, favoring values
3668/// between `min` and `max_inbounds`.
3669///
3670/// The thinking behind this function is that it's used for things like offsets
3671/// and minimum sizes which, when very large, can trivially make the wasm oom or
3672/// abort with a trap. This isn't the most interesting thing to do so it tries
3673/// to favor numbers in the `min..max_inbounds` range to avoid immediate ooms.
3674fn gradually_grow(u: &mut Unstructured, min: u64, max_inbounds: u64, max: u64) -> Result<u64> {
3675    if min == max {
3676        return Ok(min);
3677    }
3678    let x = {
3679        let min = min as f64;
3680        let max = max as f64;
3681        let max_inbounds = max_inbounds as f64;
3682        let x = u.arbitrary::<u32>()?;
3683        let x = f64::from(x);
3684        let x = map_custom(
3685            x,
3686            f64::from(u32::MIN)..f64::from(u32::MAX),
3687            min..max_inbounds,
3688            min..max,
3689        );
3690        assert!(min <= x, "{min} <= {x}");
3691        assert!(x <= max, "{x} <= {max}");
3692        x.round() as u64
3693    };
3694
3695    // Conversion between `u64` and `f64` is lossy, especially for large
3696    // numbers, so just clamp the final result.
3697    return Ok(x.clamp(min, max));
3698
3699    /// Map a value from within the input range to the output range(s).
3700    ///
3701    /// This will first map the input range into the `0..1` input range, and
3702    /// then depending on the value it will either map it exponentially
3703    /// (favoring small values) into the `output_inbounds` range or it will map
3704    /// it into the `output` range.
3705    fn map_custom(
3706        value: f64,
3707        input: Range<f64>,
3708        output_inbounds: Range<f64>,
3709        output: Range<f64>,
3710    ) -> f64 {
3711        assert!(!value.is_nan(), "{}", value);
3712        assert!(value.is_finite(), "{}", value);
3713        assert!(input.start < input.end, "{} < {}", input.start, input.end);
3714        assert!(
3715            output.start < output.end,
3716            "{} < {}",
3717            output.start,
3718            output.end
3719        );
3720        assert!(value >= input.start, "{} >= {}", value, input.start);
3721        assert!(value <= input.end, "{} <= {}", value, input.end);
3722        assert!(
3723            output.start <= output_inbounds.start,
3724            "{} <= {}",
3725            output.start,
3726            output_inbounds.start
3727        );
3728        assert!(
3729            output_inbounds.end <= output.end,
3730            "{} <= {}",
3731            output_inbounds.end,
3732            output.end
3733        );
3734
3735        let x = map_linear(value, input, 0.0..1.0);
3736        let result = if x < PCT_INBOUNDS {
3737            if output_inbounds.start == output_inbounds.end {
3738                output_inbounds.start
3739            } else {
3740                let unscaled = x * x * x * x * x * x;
3741                map_linear(unscaled, 0.0..1.0, output_inbounds)
3742            }
3743        } else {
3744            map_linear(x, 0.0..1.0, output.clone())
3745        };
3746
3747        assert!(result >= output.start, "{} >= {}", result, output.start);
3748        assert!(result <= output.end, "{} <= {}", result, output.end);
3749        result
3750    }
3751
3752    /// Map a value from within the input range linearly to the output range.
3753    ///
3754    /// For example, mapping `0.5` from the input range `0.0..1.0` to the output
3755    /// range `1.0..3.0` produces `2.0`.
3756    fn map_linear(
3757        value: f64,
3758        Range {
3759            start: in_low,
3760            end: in_high,
3761        }: Range<f64>,
3762        Range {
3763            start: out_low,
3764            end: out_high,
3765        }: Range<f64>,
3766    ) -> f64 {
3767        assert!(!value.is_nan(), "{}", value);
3768        assert!(value.is_finite(), "{}", value);
3769        assert!(in_low < in_high, "{in_low} < {in_high}");
3770        assert!(out_low < out_high, "{out_low} < {out_high}");
3771        assert!(value >= in_low, "{value} >= {in_low}");
3772        assert!(value <= in_high, "{value} <= {in_high}");
3773
3774        let dividend = out_high - out_low;
3775        let divisor = in_high - in_low;
3776        let slope = dividend / divisor;
3777        let result = out_low + (slope * (value - in_low));
3778
3779        assert!(result >= out_low, "{result} >= {out_low}");
3780        assert!(result <= out_high, "{result} <= {out_high}");
3781        result
3782    }
3783}
3784
3785/// Selects a reasonable offset for an element or data segment. This favors
3786/// having the segment being in-bounds, but it may still generate
3787/// any offset.
3788fn arbitrary_offset(
3789    u: &mut Unstructured,
3790    limit_min: u64,
3791    limit_max: u64,
3792    segment_size: usize,
3793) -> Result<u64> {
3794    let size = u64::try_from(segment_size).unwrap();
3795
3796    // If the segment is too big for the whole memory, just give it any
3797    // offset.
3798    if size > limit_min {
3799        u.int_in_range(0..=limit_max)
3800    } else {
3801        gradually_grow(u, 0, limit_min - size, limit_max)
3802    }
3803}
3804
3805fn arbitrary_vec_u8(u: &mut Unstructured) -> Result<Vec<u8>> {
3806    let size = u.arbitrary_len::<u8>()?;
3807    Ok(u.bytes(size)?.to_vec())
3808}
3809
3810impl EntityType {
3811    fn size(&self) -> u32 {
3812        match self {
3813            EntityType::Tag(_)
3814            | EntityType::Global(_)
3815            | EntityType::Table(_)
3816            | EntityType::Memory(_) => 1,
3817            EntityType::Func(_, ty) => 1 + (ty.params.len() + ty.results.len()) as u32,
3818        }
3819    }
3820}
3821
3822/// A container for the kinds of instructions that wasm-smith is allowed to
3823/// emit.
3824///
3825/// # Example
3826///
3827/// ```
3828/// # use wasm_smith::{InstructionKinds, InstructionKind};
3829/// let kinds = InstructionKinds::new(&[InstructionKind::Numeric, InstructionKind::Memory]);
3830/// assert!(kinds.contains(InstructionKind::Memory));
3831/// ```
3832#[derive(Clone, Copy, Debug, Default)]
3833#[cfg_attr(
3834    feature = "serde",
3835    derive(serde_derive::Deserialize, serde_derive::Serialize)
3836)]
3837pub struct InstructionKinds(pub(crate) FlagSet<InstructionKind>);
3838
3839impl InstructionKinds {
3840    /// Create a new container.
3841    pub fn new(kinds: &[InstructionKind]) -> Self {
3842        Self(kinds.iter().fold(FlagSet::default(), |ks, k| ks | *k))
3843    }
3844
3845    /// Include all [InstructionKind]s.
3846    pub fn all() -> Self {
3847        Self(FlagSet::full())
3848    }
3849
3850    /// Include no [InstructionKind]s.
3851    pub fn none() -> Self {
3852        Self(FlagSet::default())
3853    }
3854
3855    /// Check if the [InstructionKind] is contained in this set.
3856    #[inline]
3857    pub fn contains(&self, kind: InstructionKind) -> bool {
3858        self.0.contains(kind)
3859    }
3860
3861    /// Restrict each [InstructionKind] to its subset not involving floats
3862    pub fn without_floats(&self) -> Self {
3863        let mut floatless = self.0;
3864        if floatless.contains(InstructionKind::Numeric) {
3865            floatless -= InstructionKind::Numeric;
3866            floatless |= InstructionKind::NumericInt;
3867        }
3868        if floatless.contains(InstructionKind::Vector) {
3869            floatless -= InstructionKind::Vector;
3870            floatless |= InstructionKind::VectorInt;
3871        }
3872        if floatless.contains(InstructionKind::Memory) {
3873            floatless -= InstructionKind::Memory;
3874            floatless |= InstructionKind::MemoryInt;
3875        }
3876        Self(floatless)
3877    }
3878}
3879
3880flags! {
3881    /// Enumerate the categories of instructions defined in the [WebAssembly
3882    /// specification](https://webassembly.github.io/spec/core/syntax/instructions.html).
3883    #[allow(missing_docs)]
3884    #[cfg_attr(feature = "_internal_cli", derive(serde_derive::Deserialize))]
3885    pub enum InstructionKind: u16 {
3886        NumericInt = 1 << 0,
3887        Numeric = (1 << 1) | (1 << 0),
3888        VectorInt = 1 << 2,
3889        Vector = (1 << 3) | (1 << 2),
3890        Reference = 1 << 4,
3891        Parametric = 1 << 5,
3892        Variable = 1 << 6,
3893        Table = 1 << 7,
3894        MemoryInt = 1 << 8,
3895        Memory = (1 << 9) | (1 << 8),
3896        Control = 1 << 10,
3897        Aggregate = 1 << 11,
3898    }
3899}
3900
3901impl FromStr for InstructionKinds {
3902    type Err = String;
3903    fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
3904        let mut kinds = vec![];
3905        for part in s.split(",") {
3906            let kind = InstructionKind::from_str(part)?;
3907            kinds.push(kind);
3908        }
3909        Ok(InstructionKinds::new(&kinds))
3910    }
3911}
3912
3913impl FromStr for InstructionKind {
3914    type Err = String;
3915    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
3916        match s.to_lowercase().as_str() {
3917            "numeric_non_float" => Ok(InstructionKind::NumericInt),
3918            "numeric" => Ok(InstructionKind::Numeric),
3919            "vector_non_float" => Ok(InstructionKind::VectorInt),
3920            "vector" => Ok(InstructionKind::Vector),
3921            "reference" => Ok(InstructionKind::Reference),
3922            "parametric" => Ok(InstructionKind::Parametric),
3923            "variable" => Ok(InstructionKind::Variable),
3924            "table" => Ok(InstructionKind::Table),
3925            "memory_non_float" => Ok(InstructionKind::MemoryInt),
3926            "memory" => Ok(InstructionKind::Memory),
3927            "control" => Ok(InstructionKind::Control),
3928            "aggregate" => Ok(InstructionKind::Aggregate),
3929            _ => Err(format!("unknown instruction kind: {s}")),
3930        }
3931    }
3932}
3933
3934// Conversions from `wasmparser` to `wasm-smith`. Currently, only type conversions
3935// have been implemented.
3936#[cfg(feature = "wasmparser")]
3937impl TryFrom<wasmparser::FuncType> for FuncType {
3938    type Error = ();
3939
3940    fn try_from(value: wasmparser::FuncType) -> Result<Self, Self::Error> {
3941        Ok(FuncType {
3942            params: value
3943                .params()
3944                .iter()
3945                .copied()
3946                .map(|ty| ty.try_into().map_err(|_| ()))
3947                .collect::<Result<Vec<_>, _>>()?,
3948            results: value
3949                .results()
3950                .iter()
3951                .copied()
3952                .map(|ty| ty.try_into().map_err(|_| ()))
3953                .collect::<Result<Vec<_>, _>>()?,
3954        })
3955    }
3956}
3957
3958#[cfg(feature = "wasmparser")]
3959impl TryFrom<wasmparser::CompositeType> for CompositeType {
3960    type Error = ();
3961
3962    fn try_from(value: wasmparser::CompositeType) -> Result<Self, Self::Error> {
3963        let inner_type = match value.inner {
3964            wasmparser::CompositeInnerType::Func(func_type) => {
3965                CompositeInnerType::Func(Rc::new(func_type.try_into()?))
3966            }
3967            wasmparser::CompositeInnerType::Array(array_type) => {
3968                CompositeInnerType::Array(array_type.try_into().map_err(|_| ())?)
3969            }
3970            wasmparser::CompositeInnerType::Struct(struct_type) => {
3971                CompositeInnerType::Struct(struct_type.try_into().map_err(|_| ())?)
3972            }
3973            wasmparser::CompositeInnerType::Cont(_) => {
3974                panic!("continuation type is not supported by wasm-smith currently.")
3975            }
3976        };
3977
3978        Ok(CompositeType {
3979            inner: inner_type,
3980            shared: value.shared,
3981            descriptor: value
3982                .descriptor_idx
3983                .map(|idx| idx.as_module_index().ok_or(()))
3984                .transpose()?,
3985            describes: value
3986                .describes_idx
3987                .map(|idx| idx.as_module_index().ok_or(()))
3988                .transpose()?,
3989        })
3990    }
3991}
3992
3993#[cfg(feature = "wasmparser")]
3994impl TryFrom<wasmparser::SubType> for SubType {
3995    type Error = ();
3996
3997    fn try_from(value: wasmparser::SubType) -> Result<Self, Self::Error> {
3998        Ok(SubType {
3999            is_final: value.is_final,
4000            supertype: value
4001                .supertype_idx
4002                .map(|idx| idx.as_module_index().ok_or(()))
4003                .transpose()?,
4004            composite_type: value.composite_type.try_into()?,
4005            // We cannot determine the depth of current subtype here, set it to 1
4006            // temporarily and fix it later.
4007            depth: 1,
4008        })
4009    }
4010}