wasm_smith/
core.rs

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