Skip to main content

wasm_smith/
core.rs

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