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