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