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 const MAX_CONST_EXPR_RECURSION_DEPTH: usize = 8;
2048
2049 #[derive(Clone, Copy)]
2050 enum Choice {
2051 GlobalGet(u32),
2052 I32Const,
2053 I64Const,
2054 F32Const,
2055 F64Const,
2056 V128Const,
2057 ExtendedConst,
2058 RefNull(HeapType),
2059 RefFunc(u32),
2060 StructNew(u32),
2061 StructNewDefault(u32),
2062 ArrayNew(u32),
2063 ArrayNewDefault(u32),
2064 ArrayNewFixed(u32),
2065 RefI31 { shared: bool },
2066 AnyConvertExtern { nullable: bool, shared: bool },
2067 ExternConvertAny { nullable: bool, shared: bool },
2068 }
2069
2070 fn encode_instrs(instrs: impl IntoIterator<Item = Instruction>) -> Vec<u8> {
2071 let mut bytes = Vec::new();
2072 for instr in instrs {
2073 instr.encode(&mut bytes);
2074 }
2075 bytes
2076 }
2077
2078 fn arbitrary_extended_const(u: &mut Unstructured<'_>, ty: ValType) -> Result<Vec<u8>> {
2086 use wasm_encoder::Instruction::*;
2087
2088 assert!(ty == ValType::I32 || ty == ValType::I64);
2091 let add = if ty == ValType::I32 { I32Add } else { I64Add };
2092 let sub = if ty == ValType::I32 { I32Sub } else { I64Sub };
2093 let mul = if ty == ValType::I32 { I32Mul } else { I64Mul };
2094 let const_: fn(&mut Unstructured<'_>) -> Result<Instruction> = if ty == ValType::I32 {
2095 |u| u.arbitrary().map(I32Const)
2096 } else {
2097 |u| u.arbitrary().map(I64Const)
2098 };
2099
2100 let mut instrs = Vec::new();
2105 let mut needed = 1;
2106 while needed > 0 {
2107 let choice = if u.is_empty() || instrs.len() > 10 {
2111 0
2112 } else {
2113 u.int_in_range(0..=3)?
2114 };
2115 match choice {
2116 0 => {
2117 instrs.push(const_(u)?);
2118 needed -= 1;
2119 }
2120 1 => {
2121 instrs.push(add.clone());
2122 needed += 1;
2123 }
2124 2 => {
2125 instrs.push(sub.clone());
2126 needed += 1;
2127 }
2128 3 => {
2129 instrs.push(mul.clone());
2130 needed += 1;
2131 }
2132 _ => unreachable!(),
2133 }
2134 }
2135 Ok(encode_instrs(instrs.into_iter().rev()))
2136 }
2137
2138 fn abstract_ref(nullable: bool, shared: bool, ty: AbstractHeapType) -> RefType {
2139 RefType::new_abstract(ty, nullable, shared)
2140 }
2141
2142 fn concrete_ref(nullable: bool, ty: u32) -> RefType {
2143 RefType {
2144 nullable,
2145 heap_type: HeapType::Concrete(ty),
2146 }
2147 }
2148
2149 fn type_is_defaultable(field: StorageType) -> bool {
2150 field.unpack().is_defaultable()
2151 }
2152
2153 fn can_use_struct_new(ty: &SubType) -> bool {
2154 ty.composite_type.descriptor.is_none()
2155 }
2156
2157 fn can_use_struct_new_default(ty: &SubType) -> bool {
2158 can_use_struct_new(ty)
2159 && ty
2160 .unwrap_struct()
2161 .fields
2162 .iter()
2163 .all(|f| type_is_defaultable(f.element_type))
2164 }
2165
2166 fn const_expr_bytes(
2167 module: &mut Module,
2168 ty: ValType,
2169 u: &mut Unstructured<'_>,
2170 allow_defined_globals: bool,
2171 fuel: usize,
2172 ) -> Result<Vec<u8>> {
2173 let mut choices = Vec::new();
2174
2175 for i in module.globals_for_const_expr(ty, allow_defined_globals) {
2176 choices.push(Choice::GlobalGet(i));
2177 }
2178
2179 let ty = match ty {
2180 ValType::Ref(_) => ty,
2181 _ => module.arbitrary_matching_val_type(u, ty)?,
2182 };
2183 match ty {
2184 ValType::I32 => {
2185 choices.push(Choice::I32Const);
2186 if module.config.extended_const_enabled {
2187 choices.push(Choice::ExtendedConst);
2188 }
2189 }
2190 ValType::I64 => {
2191 choices.push(Choice::I64Const);
2192 if module.config.extended_const_enabled {
2193 choices.push(Choice::ExtendedConst);
2194 }
2195 }
2196 ValType::F32 => choices.push(Choice::F32Const),
2197 ValType::F64 => choices.push(Choice::F64Const),
2198 ValType::V128 => choices.push(Choice::V128Const),
2199 ValType::Ref(ref_ty) => {
2200 if ref_ty.nullable {
2201 choices.push(Choice::RefNull(ref_ty.heap_type));
2202 }
2203
2204 for (func_idx, (type_idx, _)) in module.funcs.iter().enumerate() {
2205 let produced = concrete_ref(false, *type_idx);
2206 if module.ref_type_is_sub_type(produced, ref_ty) {
2207 choices.push(Choice::RefFunc(func_idx as u32));
2208 }
2209 }
2210
2211 if module.config.gc_enabled {
2212 for &type_idx in &module.struct_types {
2213 let produced = concrete_ref(false, type_idx);
2214 if !module.ref_type_is_sub_type(produced, ref_ty) {
2215 continue;
2216 }
2217 if can_use_struct_new(module.ty(type_idx))
2218 && (fuel > 0
2219 || module.ty(type_idx).unwrap_struct().fields.is_empty())
2220 {
2221 choices.push(Choice::StructNew(type_idx));
2222 }
2223 if can_use_struct_new_default(module.ty(type_idx)) {
2224 choices.push(Choice::StructNewDefault(type_idx));
2225 }
2226 }
2227
2228 for &type_idx in &module.array_types {
2229 let produced = concrete_ref(false, type_idx);
2230 if !module.ref_type_is_sub_type(produced, ref_ty) {
2231 continue;
2232 }
2233 if fuel > 0 {
2234 choices.push(Choice::ArrayNew(type_idx));
2235 choices.push(Choice::ArrayNewFixed(type_idx));
2236 if type_is_defaultable(
2237 module.ty(type_idx).unwrap_array().0.element_type,
2238 ) {
2239 choices.push(Choice::ArrayNewDefault(type_idx));
2240 }
2241 }
2242 }
2243
2244 let produced_i31 = abstract_ref(false, false, AbstractHeapType::I31);
2245 if fuel > 0 && module.ref_type_is_sub_type(produced_i31, ref_ty) {
2246 choices.push(Choice::RefI31 { shared: false });
2247 }
2248
2249 if module.config.shared_everything_threads_enabled {
2250 let produced_i31 = abstract_ref(false, true, AbstractHeapType::I31);
2251 if fuel > 0 && module.ref_type_is_sub_type(produced_i31, ref_ty) {
2252 choices.push(Choice::RefI31 { shared: true });
2253 }
2254 }
2255
2256 match ref_ty.heap_type {
2257 HeapType::Abstract {
2258 shared,
2259 ty: AbstractHeapType::Any,
2260 } if fuel > 0 => {
2261 choices.push(Choice::AnyConvertExtern {
2262 nullable: ref_ty.nullable,
2263 shared,
2264 });
2265 }
2266 HeapType::Abstract {
2267 shared,
2268 ty: AbstractHeapType::Extern,
2269 } if fuel > 0 => {
2270 choices.push(Choice::ExternConvertAny {
2271 nullable: ref_ty.nullable,
2272 shared,
2273 });
2274 }
2275 _ => {}
2276 }
2277 }
2278 }
2279 }
2280
2281 let choice = *u.choose(&choices)?;
2282 Ok(match choice {
2283 Choice::GlobalGet(i) => encode_instrs([Instruction::GlobalGet(i)]),
2284 Choice::I32Const => encode_instrs([Instruction::I32Const(u.arbitrary()?)]),
2285 Choice::I64Const => encode_instrs([Instruction::I64Const(u.arbitrary()?)]),
2286 Choice::F32Const => {
2287 encode_instrs([Instruction::F32Const(u.arbitrary::<f32>()?.into())])
2288 }
2289 Choice::F64Const => {
2290 encode_instrs([Instruction::F64Const(u.arbitrary::<f64>()?.into())])
2291 }
2292 Choice::V128Const => encode_instrs([Instruction::V128Const(u.arbitrary()?)]),
2293 Choice::ExtendedConst => arbitrary_extended_const(u, ty)?,
2294 Choice::RefNull(heap_type) => encode_instrs([Instruction::RefNull(heap_type)]),
2295 Choice::RefFunc(i) => encode_instrs([Instruction::RefFunc(i)]),
2296 Choice::StructNew(type_idx) => {
2297 let mut bytes = Vec::new();
2298 let field_types: Vec<_> = module
2299 .ty(type_idx)
2300 .unwrap_struct()
2301 .fields
2302 .iter()
2303 .map(|field| field.element_type.unpack())
2304 .collect();
2305 for field_ty in field_types {
2306 bytes.extend(const_expr_bytes(
2307 module,
2308 field_ty,
2309 u,
2310 allow_defined_globals,
2311 fuel.saturating_sub(1),
2312 )?);
2313 }
2314 bytes.extend(encode_instrs([Instruction::StructNew(type_idx)]));
2315 bytes
2316 }
2317 Choice::StructNewDefault(type_idx) => {
2318 encode_instrs([Instruction::StructNewDefault(type_idx)])
2319 }
2320 Choice::ArrayNew(type_idx) => {
2321 let mut bytes = Vec::new();
2322 let elem_ty = module.ty(type_idx).unwrap_array().0.element_type.unpack();
2323 bytes.extend(const_expr_bytes(
2324 module,
2325 elem_ty,
2326 u,
2327 allow_defined_globals,
2328 fuel.saturating_sub(1),
2329 )?);
2330 bytes.extend(const_expr_bytes(
2331 module,
2332 ValType::I32,
2333 u,
2334 allow_defined_globals,
2335 fuel.saturating_sub(1),
2336 )?);
2337 bytes.extend(encode_instrs([Instruction::ArrayNew(type_idx)]));
2338 bytes
2339 }
2340 Choice::ArrayNewDefault(type_idx) => {
2341 let mut bytes = const_expr_bytes(
2342 module,
2343 ValType::I32,
2344 u,
2345 allow_defined_globals,
2346 fuel.saturating_sub(1),
2347 )?;
2348 bytes.extend(encode_instrs([Instruction::ArrayNewDefault(type_idx)]));
2349 bytes
2350 }
2351 Choice::ArrayNewFixed(type_idx) => {
2352 let array_size = u.int_in_range(0..=3)?;
2353 let array_size = u32::try_from(array_size).unwrap();
2354 let elem_ty = module.ty(type_idx).unwrap_array().0.element_type.unpack();
2355 let mut bytes = Vec::new();
2356 for _ in 0..array_size {
2357 bytes.extend(const_expr_bytes(
2358 module,
2359 elem_ty,
2360 u,
2361 allow_defined_globals,
2362 fuel.saturating_sub(1),
2363 )?);
2364 }
2365 bytes.extend(encode_instrs([Instruction::ArrayNewFixed {
2366 array_type_index: type_idx,
2367 array_size,
2368 }]));
2369 bytes
2370 }
2371 Choice::RefI31 { shared } => {
2372 let mut bytes = const_expr_bytes(
2373 module,
2374 ValType::I32,
2375 u,
2376 allow_defined_globals,
2377 fuel.saturating_sub(1),
2378 )?;
2379 bytes.extend(encode_instrs([if shared {
2380 Instruction::RefI31Shared
2381 } else {
2382 Instruction::RefI31
2383 }]));
2384 bytes
2385 }
2386 Choice::AnyConvertExtern { nullable, shared } => {
2387 let mut bytes = const_expr_bytes(
2388 module,
2389 ValType::Ref(abstract_ref(nullable, shared, AbstractHeapType::Extern)),
2390 u,
2391 allow_defined_globals,
2392 fuel.saturating_sub(1),
2393 )?;
2394 bytes.extend(encode_instrs([Instruction::AnyConvertExtern]));
2395 bytes
2396 }
2397 Choice::ExternConvertAny { nullable, shared } => {
2398 let mut bytes = const_expr_bytes(
2399 module,
2400 ValType::Ref(abstract_ref(nullable, shared, AbstractHeapType::Any)),
2401 u,
2402 allow_defined_globals,
2403 fuel.saturating_sub(1),
2404 )?;
2405 bytes.extend(encode_instrs([Instruction::ExternConvertAny]));
2406 bytes
2407 }
2408 })
2409 }
2410
2411 Ok(ConstExpr::raw(const_expr_bytes(
2412 self,
2413 ty,
2414 u,
2415 allow_defined_globals,
2416 MAX_CONST_EXPR_RECURSION_DEPTH,
2417 )?))
2418 }
2419
2420 fn arbitrary_globals(&mut self, u: &mut Unstructured) -> Result<()> {
2421 arbitrary_loop(u, self.config.min_globals, self.config.max_globals, |u| {
2422 if !self.can_add_local_or_import_global() {
2423 return Ok(false);
2424 }
2425
2426 let ty = self.arbitrary_global_type(u)?;
2427 self.add_arbitrary_global_of_type(ty, u)?;
2428
2429 Ok(true)
2430 })
2431 }
2432
2433 fn required_exports(&mut self, u: &mut Unstructured) -> Result<bool> {
2434 let example_module = if let Some(wasm) = self.config.exports.clone() {
2435 wasm
2436 } else {
2437 return Ok(false);
2438 };
2439
2440 #[cfg(feature = "wasmparser")]
2441 {
2442 self._required_exports(u, &example_module)?;
2443 Ok(true)
2444 }
2445 #[cfg(not(feature = "wasmparser"))]
2446 {
2447 let _ = (example_module, u);
2448 panic!("support for `exports` was disabled at compile time");
2449 }
2450 }
2451
2452 #[cfg(feature = "wasmparser")]
2453 fn _required_exports(&mut self, u: &mut Unstructured, example_module: &[u8]) -> Result<()> {
2454 let mut required_exports: Vec<wasmparser::Export> = vec![];
2455 let mut validator = wasmparser::Validator::new();
2456 let exports_types = validator
2457 .validate_all(&example_module)
2458 .expect("Failed to validate `exports` Wasm");
2459 for payload in wasmparser::Parser::new(0).parse_all(&example_module) {
2460 match payload.expect("Failed to read `exports` Wasm") {
2461 wasmparser::Payload::ExportSection(export_reader) => {
2462 required_exports = export_reader
2463 .into_iter()
2464 .collect::<Result<_, _>>()
2465 .expect("Failed to read `exports` export section");
2466 }
2467 _ => {}
2468 }
2469 }
2470
2471 let exports_types = exports_types.as_ref();
2473 let check_and_get_func_type =
2474 |id: wasmparser::types::CoreTypeId| -> (Rc<FuncType>, SubType) {
2475 let subtype = exports_types.get(id).unwrap_or_else(|| {
2476 panic!("Unable to get subtype for {id:?} in `exports` Wasm")
2477 });
2478 match &subtype.composite_type.inner {
2479 wasmparser::CompositeInnerType::Func(func_type) => {
2480 assert!(
2481 subtype.is_final,
2482 "Subtype {subtype:?} from `exports` Wasm is not final"
2483 );
2484 assert!(
2485 subtype.supertype_idx.is_none(),
2486 "Subtype {subtype:?} from `exports` Wasm has non-empty supertype"
2487 );
2488 let func_type = Rc::new(FuncType {
2489 params: func_type
2490 .params()
2491 .iter()
2492 .copied()
2493 .map(|t| t.try_into().unwrap())
2494 .collect(),
2495 results: func_type
2496 .results()
2497 .iter()
2498 .copied()
2499 .map(|t| t.try_into().unwrap())
2500 .collect(),
2501 });
2502 let subtype = SubType {
2503 is_final: true,
2504 supertype: None,
2505 depth: 1,
2506 composite_type: CompositeType::new_func(
2507 Rc::clone(&func_type),
2508 subtype.composite_type.shared,
2509 ),
2510 };
2511 (func_type, subtype)
2512 }
2513 _ => panic!(
2514 "Unable to handle type {:?} from `exports` Wasm",
2515 subtype.composite_type
2516 ),
2517 }
2518 };
2519 for export in required_exports {
2520 let new_index = match exports_types
2521 .entity_type_from_export(&export)
2522 .unwrap_or_else(|| {
2523 panic!("Unable to get type from export {export:?} in `exports` Wasm",)
2524 }) {
2525 wasmparser::types::EntityType::Func(id) => {
2527 let (func_type, subtype) = check_and_get_func_type(id);
2528 self.rec_groups.push(self.types.len()..self.types.len() + 1);
2529 let type_index = self.add_type(subtype);
2530 let func_index = self.funcs.len() as u32;
2531 self.funcs.push((type_index, func_type));
2532 self.num_defined_funcs += 1;
2533 func_index
2534 }
2535 wasmparser::types::EntityType::Global(global_type) => {
2537 self.add_arbitrary_global_of_type(global_type.try_into().unwrap(), u)?
2538 }
2539 wasmparser::types::EntityType::Memory(memory_type) => {
2541 self.add_arbitrary_memory_of_type(memory_type.into())?
2542 }
2543 wasmparser::types::EntityType::Table(table_type) => {
2545 self.add_arbitrary_table_of_type(table_type.try_into().unwrap(), u)?
2546 }
2547 wasmparser::types::EntityType::Tag(id) => {
2549 let (func_type, subtype) = check_and_get_func_type(id);
2550 self.rec_groups.push(self.types.len()..self.types.len() + 1);
2551 let type_index = self.add_type(subtype);
2552 let tag_index = self.tags.len() as u32;
2553 self.tags.push(TagType {
2554 func_type_idx: type_index,
2555 func_type: func_type,
2556 });
2557 self.num_defined_tags += 1;
2558 tag_index
2559 }
2560 wasmparser::types::EntityType::FuncExact(_) => {
2561 panic!("Unexpected func_export: {export:?}",);
2562 }
2563 };
2564 self.exports
2565 .push((export.name.to_string(), export.kind.into(), new_index));
2566 self.export_names.insert(export.name.to_string());
2567 }
2568
2569 Ok(())
2570 }
2571
2572 fn arbitrary_exports(&mut self, u: &mut Unstructured) -> Result<()> {
2573 if self.config.max_type_size < self.type_size && !self.config.export_everything {
2574 return Ok(());
2575 }
2576
2577 let mut choices: Vec<Vec<(ExportKind, u32)>> = Vec::with_capacity(6);
2579 choices.push(
2580 (0..self.funcs.len())
2581 .map(|i| (ExportKind::Func, i as u32))
2582 .collect(),
2583 );
2584 choices.push(
2585 (0..self.tables.len())
2586 .map(|i| (ExportKind::Table, i as u32))
2587 .collect(),
2588 );
2589 choices.push(
2590 (0..self.memories.len())
2591 .map(|i| (ExportKind::Memory, i as u32))
2592 .collect(),
2593 );
2594 choices.push(
2595 (0..self.globals.len())
2596 .map(|i| (ExportKind::Global, i as u32))
2597 .collect(),
2598 );
2599
2600 if self.config.export_everything {
2603 for choices_by_kind in choices {
2604 for (kind, idx) in choices_by_kind {
2605 let name = unique_string(1_000, &mut self.export_names, u)?;
2606 self.add_arbitrary_export(name, kind, idx)?;
2607 }
2608 }
2609 return Ok(());
2610 }
2611
2612 arbitrary_loop(u, self.config.min_exports, self.config.max_exports, |u| {
2613 let max_size = self.config.max_type_size - self.type_size;
2619 for list in choices.iter_mut() {
2620 list.retain(|(kind, idx)| self.type_of(*kind, *idx).size() + 1 < max_size);
2621 }
2622 choices.retain(|list| !list.is_empty());
2623 if choices.is_empty() {
2624 return Ok(false);
2625 }
2626
2627 let name = unique_string(1_000, &mut self.export_names, u)?;
2630 let list = u.choose(&choices)?;
2631 let (kind, idx) = *u.choose(list)?;
2632 self.add_arbitrary_export(name, kind, idx)?;
2633 Ok(true)
2634 })
2635 }
2636
2637 fn add_arbitrary_export(&mut self, name: String, kind: ExportKind, idx: u32) -> Result<()> {
2638 let ty = self.type_of(kind, idx);
2639 self.type_size += 1 + ty.size();
2640 if self.type_size <= self.config.max_type_size {
2641 self.exports.push((name, kind, idx));
2642 Ok(())
2643 } else {
2644 Err(arbitrary::Error::IncorrectFormat)
2648 }
2649 }
2650
2651 fn arbitrary_start(&mut self, u: &mut Unstructured) -> Result<()> {
2652 if !self.config.allow_start_export {
2653 return Ok(());
2654 }
2655
2656 let mut choices = Vec::with_capacity(self.funcs.len());
2657
2658 for (func_idx, ty) in self.funcs() {
2659 if ty.params.is_empty() && ty.results.is_empty() {
2660 choices.push(func_idx);
2661 }
2662 }
2663
2664 if !choices.is_empty() && u.arbitrary().unwrap_or(false) {
2665 let f = *u.choose(&choices)?;
2666 self.start = Some(f);
2667 }
2668
2669 Ok(())
2670 }
2671
2672 fn arbitrary_elems(&mut self, u: &mut Unstructured) -> Result<()> {
2673 let mut global_i32 = vec![];
2675 let mut global_i64 = vec![];
2676 if !self.config.disallow_traps {
2677 for i in self.globals_for_const_expr(ValType::I32, true) {
2678 global_i32.push(i);
2679 }
2680 for i in self.globals_for_const_expr(ValType::I64, true) {
2681 global_i64.push(i);
2682 }
2683 }
2684 let disallow_traps = self.config.disallow_traps;
2685 let arbitrary_active_elem =
2686 |u: &mut Unstructured, min_mem_size: u64, table: Option<u32>, table_ty: &TableType| {
2687 let global_choices = if table_ty.table64 {
2688 &global_i64
2689 } else {
2690 &global_i32
2691 };
2692 let (offset, max_size_hint) = if !global_choices.is_empty() && u.arbitrary()? {
2693 let g = u.choose(&global_choices)?;
2694 (Offset::Global(*g), None)
2695 } else {
2696 let max_mem_size = if disallow_traps {
2697 table_ty.minimum
2698 } else if table_ty.table64 {
2699 u64::MAX
2700 } else {
2701 u64::from(u32::MAX)
2702 };
2703 let offset = arbitrary_offset(u, min_mem_size, max_mem_size, 0)?;
2704 let max_size_hint = if disallow_traps
2705 || (offset <= min_mem_size
2706 && u.int_in_range(0..=CHANCE_OFFSET_INBOUNDS)? != 0)
2707 {
2708 Some(min_mem_size - offset)
2709 } else {
2710 None
2711 };
2712
2713 let offset = if table_ty.table64 {
2714 Offset::Const64(offset as i64)
2715 } else {
2716 Offset::Const32(offset as i32)
2717 };
2718 (offset, max_size_hint)
2719 };
2720 Ok((ElementKind::Active { table, offset }, max_size_hint))
2721 };
2722
2723 type GenElemSegment<'a> =
2727 dyn Fn(&mut Unstructured) -> Result<(ElementKind, Option<u64>)> + 'a;
2728 let mut choices: Vec<Box<GenElemSegment>> = Vec::new();
2729
2730 if self.config.bulk_memory_enabled {
2733 choices.push(Box::new(|_| Ok((ElementKind::Passive, None))));
2734 choices.push(Box::new(|_| Ok((ElementKind::Declared, None))));
2735 }
2736
2737 for (i, ty) in self.tables.iter().enumerate() {
2738 if ty.minimum == 0 && u.int_in_range(0..=CHANCE_SEGMENT_ON_EMPTY)? != 0 {
2743 continue;
2744 }
2745
2746 let minimum = ty.minimum;
2747 let ty = *ty;
2750 if i == 0 && ty.element_type == RefType::FUNCREF {
2751 choices.push(Box::new(move |u| {
2752 arbitrary_active_elem(u, minimum, None, &ty)
2753 }));
2754 }
2755 if self.config.bulk_memory_enabled {
2756 let idx = Some(i as u32);
2757 choices.push(Box::new(move |u| {
2758 arbitrary_active_elem(u, minimum, idx, &ty)
2759 }));
2760 }
2761 }
2762
2763 if choices.is_empty() {
2764 return Ok(());
2765 }
2766
2767 arbitrary_loop(
2768 u,
2769 self.config.min_element_segments,
2770 self.config.max_element_segments,
2771 |u| {
2772 let (kind, max_size_hint) = u.choose(&choices)?(u)?;
2775 let max = max_size_hint
2776 .map(|i| usize::try_from(i).unwrap())
2777 .unwrap_or_else(|| self.config.max_elements);
2778
2779 let ty = match kind {
2783 ElementKind::Passive | ElementKind::Declared => self.arbitrary_ref_type(u)?,
2784 ElementKind::Active { table, .. } => {
2785 let idx = table.unwrap_or(0);
2786 self.arbitrary_matching_ref_type(u, self.tables[idx as usize].element_type)?
2787 }
2788 };
2789
2790 let can_use_function_list = ty == RefType::FUNCREF;
2794 if !self.config.reference_types_enabled {
2795 assert!(can_use_function_list);
2796 }
2797
2798 let mut func_candidates = Vec::new();
2801 if can_use_function_list {
2802 match ty.heap_type {
2803 HeapType::Abstract {
2804 ty: AbstractHeapType::Func,
2805 ..
2806 } => {
2807 func_candidates.extend(0..self.funcs.len() as u32);
2808 }
2809 HeapType::Concrete(ty) => {
2810 for (i, (fty, _)) in self.funcs.iter().enumerate() {
2811 if *fty == ty {
2812 func_candidates.push(i as u32);
2813 }
2814 }
2815 }
2816 _ => {}
2817 }
2818 }
2819
2820 let items = if !self.config.reference_types_enabled
2825 || (can_use_function_list && u.arbitrary()?)
2826 {
2827 let mut init = vec![];
2828 if func_candidates.len() > 0 {
2829 arbitrary_loop(u, self.config.min_elements, max, |u| {
2830 let func_idx = *u.choose(&func_candidates)?;
2831 init.push(func_idx);
2832 Ok(true)
2833 })?;
2834 }
2835 Elements::Functions(init)
2836 } else {
2837 let mut init = vec![];
2838 arbitrary_loop(u, self.config.min_elements, max, |u| {
2839 init.push(self.arbitrary_const_expr(ValType::Ref(ty), u, true)?);
2840 Ok(true)
2841 })?;
2842 Elements::Expressions(init)
2843 };
2844
2845 self.elems.push(ElementSegment { kind, ty, items });
2846 Ok(true)
2847 },
2848 )
2849 }
2850
2851 fn arbitrary_code(&mut self, u: &mut Unstructured) -> Result<()> {
2852 self.compute_interesting_values();
2853
2854 self.code.reserve(self.num_defined_funcs);
2855 let mut allocs = CodeBuilderAllocations::new(
2856 self,
2857 self.config.exports.is_some() || self.config.module_shape.is_some(),
2858 );
2859 for (idx, ty) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() {
2860 let shared = self.is_shared_type(*idx);
2861 let body = self.arbitrary_func_body(u, ty, &mut allocs, shared)?;
2862 self.code.push(body);
2863 }
2864 allocs.finish(u, self)?;
2865 Ok(())
2866 }
2867
2868 fn arbitrary_func_body(
2869 &self,
2870 u: &mut Unstructured,
2871 ty: &FuncType,
2872 allocs: &mut CodeBuilderAllocations,
2873 shared: bool,
2874 ) -> Result<Code> {
2875 let mut locals = self.arbitrary_locals(u)?;
2876 let builder = allocs.builder(ty, &mut locals, shared);
2877 let instructions = if self.config.allow_invalid_funcs && u.arbitrary().unwrap_or(false) {
2878 Instructions::Arbitrary(arbitrary_vec_u8(u)?)
2879 } else {
2880 Instructions::Generated(builder.arbitrary(u, self)?)
2881 };
2882
2883 Ok(Code {
2884 locals,
2885 instructions,
2886 })
2887 }
2888
2889 fn arbitrary_locals(&self, u: &mut Unstructured) -> Result<Vec<ValType>> {
2890 let mut ret = Vec::new();
2891 arbitrary_loop(u, 0, 100, |u| {
2892 ret.push(self.arbitrary_valtype(u)?);
2893 Ok(true)
2894 })?;
2895 Ok(ret)
2896 }
2897
2898 fn arbitrary_data(&mut self, u: &mut Unstructured) -> Result<()> {
2899 let memories = self.memories.len() as u32;
2902 if memories == 0 && !self.config.bulk_memory_enabled {
2903 return Ok(());
2904 }
2905 let disallow_traps = self.config.disallow_traps;
2906 let mut choices32: Vec<Box<dyn Fn(&mut Unstructured, u64, usize) -> Result<Offset>>> =
2907 vec![];
2908 choices32.push(Box::new(|u, min_size, data_len| {
2909 let min = u32::try_from(min_size.saturating_mul(64 * 1024))
2910 .unwrap_or(u32::MAX)
2911 .into();
2912 let max = if disallow_traps { min } else { u32::MAX.into() };
2913 Ok(Offset::Const32(
2914 arbitrary_offset(u, min, max, data_len)? as i32
2915 ))
2916 }));
2917 let mut choices64: Vec<Box<dyn Fn(&mut Unstructured, u64, usize) -> Result<Offset>>> =
2918 vec![];
2919 choices64.push(Box::new(|u, min_size, data_len| {
2920 let min = min_size.saturating_mul(64 * 1024);
2921 let max = if disallow_traps { min } else { u64::MAX };
2922 Ok(Offset::Const64(
2923 arbitrary_offset(u, min, max, data_len)? as i64
2924 ))
2925 }));
2926 if !self.config.disallow_traps {
2927 for i in self.globals_for_const_expr(ValType::I32, true) {
2928 choices32.push(Box::new(move |_, _, _| Ok(Offset::Global(i))));
2929 }
2930 for i in self.globals_for_const_expr(ValType::I64, true) {
2931 choices64.push(Box::new(move |_, _, _| Ok(Offset::Global(i))));
2932 }
2933 }
2934
2935 let mut memories = Vec::new();
2941 for (i, mem) in self.memories.iter().enumerate() {
2942 if mem.minimum > 0 || u.int_in_range(0..=CHANCE_SEGMENT_ON_EMPTY)? == 0 {
2943 memories.push(i as u32);
2944 }
2945 }
2946
2947 if memories.is_empty() && !self.config.bulk_memory_enabled {
2951 return Ok(());
2952 }
2953
2954 arbitrary_loop(
2955 u,
2956 self.config.min_data_segments,
2957 self.config.max_data_segments,
2958 |u| {
2959 let mut init: Vec<u8> = u.arbitrary()?;
2960
2961 let kind =
2966 if self.config.bulk_memory_enabled && (memories.is_empty() || u.arbitrary()?) {
2967 DataSegmentKind::Passive
2968 } else {
2969 let memory_index = *u.choose(&memories)?;
2970 let mem = &self.memories[memory_index as usize];
2971 let f = if mem.memory64 {
2972 u.choose(&choices64)?
2973 } else {
2974 u.choose(&choices32)?
2975 };
2976 let mut offset = f(u, mem.minimum, init.len())?;
2977
2978 if self.config.disallow_traps {
2983 let max_size = (u64::MAX / 64 / 1024).min(mem.minimum) * 64 * 1024;
2984 init.truncate(max_size as usize);
2985 let max_offset = max_size - init.len() as u64;
2986 match &mut offset {
2987 Offset::Const32(x) => {
2988 *x = (*x as u64).min(max_offset) as i32;
2989 }
2990 Offset::Const64(x) => {
2991 *x = (*x as u64).min(max_offset) as i64;
2992 }
2993 Offset::Global(_) => unreachable!(),
2994 }
2995 }
2996 DataSegmentKind::Active {
2997 offset,
2998 memory_index,
2999 }
3000 };
3001 self.data.push(DataSegment { kind, init });
3002 Ok(true)
3003 },
3004 )
3005 }
3006
3007 fn params_results(&self, ty: &BlockType) -> (Vec<ValType>, Vec<ValType>) {
3008 match ty {
3009 BlockType::Empty => (vec![], vec![]),
3010 BlockType::Result(t) => (vec![], vec![*t]),
3011 BlockType::FunctionType(ty) => {
3012 let ty = self.func_type(*ty);
3013 (ty.params.to_vec(), ty.results.to_vec())
3014 }
3015 }
3016 }
3017
3018 fn globals_for_const_expr(
3021 &self,
3022 ty: ValType,
3023 allow_defined_globals: bool,
3024 ) -> impl Iterator<Item = u32> + '_ {
3025 let num_imported_globals = self.globals.len() - self.defined_globals.len();
3028 let max_global = if self.config.gc_enabled && allow_defined_globals {
3029 self.globals.len()
3030 } else {
3031 num_imported_globals
3032 };
3033
3034 self.globals[..max_global]
3035 .iter()
3036 .enumerate()
3037 .filter_map(move |(i, g)| {
3038 if !g.mutable && self.val_type_is_sub_type(g.val_type, ty) {
3042 Some(i as u32)
3043 } else {
3044 None
3045 }
3046 })
3047 }
3048
3049 fn compute_interesting_values(&mut self) {
3050 debug_assert!(self.interesting_values32.is_empty());
3051 debug_assert!(self.interesting_values64.is_empty());
3052
3053 let mut interesting_values32 = HashSet::new();
3054 let mut interesting_values64 = HashSet::new();
3055
3056 let mut interesting = |val: u64| {
3057 interesting_values32.insert(val as u32);
3058 interesting_values64.insert(val);
3059 };
3060
3061 interesting(0);
3063
3064 interesting(u8::MAX as _);
3066 interesting(u16::MAX as _);
3067 interesting(u32::MAX as _);
3068 interesting(u64::MAX);
3069
3070 interesting(i8::MIN as _);
3072 interesting(i16::MIN as _);
3073 interesting(i32::MIN as _);
3074 interesting(i64::MIN as _);
3075
3076 for i in 0..64 {
3077 interesting(1 << i);
3079
3080 interesting(!(1 << i));
3082
3083 interesting((1 << i) - 1);
3085
3086 interesting(((1_i64 << 63) >> i) as _);
3088 }
3089
3090 for pattern in [0b01010101, 0b00010001, 0b00010001, 0b00000001] {
3092 for b in [pattern, !pattern] {
3093 interesting(u64::from_ne_bytes([b, b, b, b, b, b, b, b]));
3094 }
3095 }
3096
3097 let mut interesting_f64 = |x: f64| interesting(x.to_bits());
3099 interesting_f64(0.0);
3100 interesting_f64(-0.0);
3101 interesting_f64(f64::INFINITY);
3102 interesting_f64(f64::NEG_INFINITY);
3103 interesting_f64(f64::EPSILON);
3104 interesting_f64(-f64::EPSILON);
3105 interesting_f64(f64::MIN);
3106 interesting_f64(f64::MIN_POSITIVE);
3107 interesting_f64(f64::MAX);
3108 interesting_f64(f64::NAN);
3109 let mut interesting_f32 = |x: f32| interesting(x.to_bits() as _);
3110 interesting_f32(0.0);
3111 interesting_f32(-0.0);
3112 interesting_f32(f32::INFINITY);
3113 interesting_f32(f32::NEG_INFINITY);
3114 interesting_f32(f32::EPSILON);
3115 interesting_f32(-f32::EPSILON);
3116 interesting_f32(f32::MIN);
3117 interesting_f32(f32::MIN_POSITIVE);
3118 interesting_f32(f32::MAX);
3119 interesting_f32(f32::NAN);
3120
3121 for t in self.tables.iter() {
3123 interesting(t.minimum as _);
3124 if let Some(x) = t.minimum.checked_add(1) {
3125 interesting(x as _);
3126 }
3127
3128 if let Some(x) = t.maximum {
3129 interesting(x as _);
3130 if let Some(y) = x.checked_add(1) {
3131 interesting(y as _);
3132 }
3133 }
3134 }
3135
3136 for m in self.memories.iter() {
3138 let min = m.minimum.saturating_mul(m.page_size().into());
3139 interesting(min);
3140 for i in 0..5 {
3141 if let Some(x) = min.checked_add(1 << i) {
3142 interesting(x);
3143 }
3144 if let Some(x) = min.checked_sub(1 << i) {
3145 interesting(x);
3146 }
3147 }
3148
3149 if let Some(max) = m.maximum {
3150 let max = max.saturating_mul(m.page_size().into());
3151 interesting(max);
3152 for i in 0..5 {
3153 if let Some(x) = max.checked_add(1 << i) {
3154 interesting(x);
3155 }
3156 if let Some(x) = max.checked_sub(1 << i) {
3157 interesting(x);
3158 }
3159 }
3160 }
3161 }
3162
3163 self.interesting_values32.extend(interesting_values32);
3164 self.interesting_values64.extend(interesting_values64);
3165
3166 self.interesting_values32.sort();
3168 self.interesting_values64.sort();
3169 }
3170
3171 fn arbitrary_const_instruction(
3172 &self,
3173 ty: ValType,
3174 u: &mut Unstructured<'_>,
3175 ) -> Result<Instruction> {
3176 debug_assert!(self.interesting_values32.len() > 0);
3177 debug_assert!(self.interesting_values64.len() > 0);
3178 match ty {
3179 ValType::I32 => Ok(Instruction::I32Const(if u.arbitrary()? {
3180 *u.choose(&self.interesting_values32)? as i32
3181 } else {
3182 u.arbitrary()?
3183 })),
3184 ValType::I64 => Ok(Instruction::I64Const(if u.arbitrary()? {
3185 *u.choose(&self.interesting_values64)? as i64
3186 } else {
3187 u.arbitrary()?
3188 })),
3189 ValType::F32 => Ok(Instruction::F32Const(if u.arbitrary()? {
3190 f32::from_bits(*u.choose(&self.interesting_values32)?).into()
3191 } else {
3192 u.arbitrary::<f32>()?.into()
3193 })),
3194 ValType::F64 => Ok(Instruction::F64Const(if u.arbitrary()? {
3195 f64::from_bits(*u.choose(&self.interesting_values64)?).into()
3196 } else {
3197 u.arbitrary::<f64>()?.into()
3198 })),
3199 ValType::V128 => Ok(Instruction::V128Const(if u.arbitrary()? {
3200 let upper = (*u.choose(&self.interesting_values64)? as i128) << 64;
3201 let lower = *u.choose(&self.interesting_values64)? as i128;
3202 upper | lower
3203 } else {
3204 u.arbitrary()?
3205 })),
3206 ValType::Ref(ty) => {
3207 assert!(ty.nullable);
3208 Ok(Instruction::RefNull(ty.heap_type))
3209 }
3210 }
3211 }
3212
3213 fn propagate_shared<T>(&mut self, must_share: bool, mut f: impl FnMut(&mut Self) -> T) -> T {
3214 let tmp = mem::replace(&mut self.must_share, must_share);
3215 let result = f(self);
3216 self.must_share = tmp;
3217 result
3218 }
3219
3220 fn arbitrary_shared(&self, u: &mut Unstructured) -> Result<bool> {
3221 if self.must_share {
3222 Ok(true)
3223 } else {
3224 Ok(self.config.shared_everything_threads_enabled && u.ratio(1, 4)?)
3225 }
3226 }
3227
3228 fn is_shared_ref_type(&self, ty: RefType) -> bool {
3229 match ty.heap_type {
3230 HeapType::Abstract { shared, .. } => shared,
3231 HeapType::Concrete(i) | HeapType::Exact(i) => {
3232 self.types[i as usize].composite_type.shared
3233 }
3234 }
3235 }
3236
3237 fn is_shared_type(&self, index: u32) -> bool {
3238 let index = usize::try_from(index).unwrap();
3239 let ty = self.types.get(index).unwrap();
3240 ty.composite_type.shared
3241 }
3242}
3243
3244pub(crate) fn arbitrary_limits64(
3245 u: &mut Unstructured,
3246 min_minimum: Option<u64>,
3247 max_minimum: u64,
3248 max_required: bool,
3249 max_inbounds: u64,
3250) -> Result<(u64, Option<u64>)> {
3251 assert!(
3252 min_minimum.unwrap_or(0) <= max_minimum,
3253 "{} <= {max_minimum}",
3254 min_minimum.unwrap_or(0),
3255 );
3256 assert!(
3257 min_minimum.unwrap_or(0) <= max_inbounds,
3258 "{} <= {max_inbounds}",
3259 min_minimum.unwrap_or(0),
3260 );
3261
3262 let min = gradually_grow(u, min_minimum.unwrap_or(0), max_inbounds, max_minimum)?;
3263 assert!(min <= max_minimum, "{min} <= {max_minimum}");
3264
3265 let max = if max_required || u.arbitrary().unwrap_or(false) {
3266 Some(u.int_in_range(min..=max_minimum)?)
3267 } else {
3268 None
3269 };
3270 assert!(min <= max.unwrap_or(min), "{min} <= {}", max.unwrap_or(min));
3271
3272 Ok((min, max))
3273}
3274
3275pub(crate) fn configured_valtypes(config: &Config) -> Vec<ValType> {
3276 let mut valtypes = Vec::with_capacity(25);
3277 valtypes.push(ValType::I32);
3278 valtypes.push(ValType::I64);
3279 if config.allow_floats {
3280 valtypes.push(ValType::F32);
3281 valtypes.push(ValType::F64);
3282 }
3283 if config.simd_enabled {
3284 valtypes.push(ValType::V128);
3285 }
3286 if config.gc_enabled && config.reference_types_enabled {
3287 for nullable in [
3288 true,
3295 ] {
3296 use AbstractHeapType::*;
3297 let abs_ref_types = [
3298 Any, Eq, I31, Array, Struct, None, Func, NoFunc, Extern, NoExtern,
3299 ];
3300 valtypes.extend(
3301 abs_ref_types
3302 .iter()
3303 .map(|&ty| ValType::Ref(RefType::new_abstract(ty, nullable, false))),
3304 );
3305 if config.shared_everything_threads_enabled {
3306 valtypes.extend(
3307 abs_ref_types
3308 .iter()
3309 .map(|&ty| ValType::Ref(RefType::new_abstract(ty, nullable, true))),
3310 );
3311 }
3312 }
3313 } else if config.reference_types_enabled {
3314 valtypes.push(ValType::EXTERNREF);
3315 valtypes.push(ValType::FUNCREF);
3316 }
3317 valtypes
3318}
3319
3320pub(crate) fn arbitrary_table_type(
3321 u: &mut Unstructured,
3322 config: &Config,
3323 module: Option<&Module>,
3324) -> Result<TableType> {
3325 let table64 = config.memory64_enabled && u.arbitrary()?;
3326 let max_inbounds = 10_000;
3329 let min_elements = if config.disallow_traps { Some(1) } else { None };
3330 let max_elements = min_elements.unwrap_or(0).max(config.max_table_elements);
3331 let (minimum, maximum) = arbitrary_limits64(
3332 u,
3333 min_elements,
3334 max_elements,
3335 config.table_max_size_required,
3336 max_inbounds.min(max_elements),
3337 )?;
3338 if config.disallow_traps {
3339 assert!(minimum > 0);
3340 }
3341 let element_type = match module {
3342 Some(module) => module.arbitrary_ref_type(u)?,
3343 None => RefType::FUNCREF,
3344 };
3345
3346 let shared = match module {
3348 Some(module) => module.is_shared_ref_type(element_type),
3349 None => false,
3350 };
3351
3352 Ok(TableType {
3353 element_type,
3354 minimum,
3355 maximum,
3356 table64,
3357 shared,
3358 })
3359}
3360
3361pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result<MemoryType> {
3362 let shared = config.threads_enabled && u.ratio(1, 4)?;
3365
3366 let memory64 = config.memory64_enabled && u.arbitrary()?;
3367 let page_size_log2 = if config.custom_page_sizes_enabled && u.arbitrary()? {
3368 Some(if u.arbitrary()? { 0 } else { 16 })
3369 } else {
3370 None
3371 };
3372
3373 let min_pages = if config.disallow_traps { Some(1) } else { None };
3374 let max_pages = min_pages.unwrap_or(0).max(if memory64 {
3375 u64::try_from(config.max_memory64_bytes >> page_size_log2.unwrap_or(16))
3376 .unwrap_or(u64::MAX)
3380 } else {
3381 u32::try_from(config.max_memory32_bytes >> page_size_log2.unwrap_or(16))
3382 .unwrap_or(u32::MAX)
3385 .into()
3386 });
3387
3388 let max_all_mems_in_bytes = 1 << 30;
3390 let max_this_mem_in_bytes = max_all_mems_in_bytes / u64::try_from(config.max_memories).unwrap();
3391 let max_inbounds = max_this_mem_in_bytes >> page_size_log2.unwrap_or(16);
3392 let max_inbounds = max_inbounds.clamp(min_pages.unwrap_or(0), max_pages);
3393
3394 let (minimum, maximum) = arbitrary_limits64(
3395 u,
3396 min_pages,
3397 max_pages,
3398 config.memory_max_size_required || shared,
3399 max_inbounds,
3400 )?;
3401
3402 Ok(MemoryType {
3403 minimum,
3404 maximum,
3405 memory64,
3406 shared,
3407 page_size_log2,
3408 })
3409}
3410
3411pub(crate) fn arbitrary_tag_type(
3412 u: &mut Unstructured,
3413 candidate_func_types: &[u32],
3414 get_func_type: impl FnOnce(u32) -> Rc<FuncType>,
3415) -> Result<TagType> {
3416 let max = candidate_func_types.len() - 1;
3417 let ty = candidate_func_types[u.int_in_range(0..=max)?];
3418 Ok(TagType {
3419 func_type_idx: ty,
3420 func_type: get_func_type(ty),
3421 })
3422}
3423
3424fn gradually_grow(u: &mut Unstructured, min: u64, max_inbounds: u64, max: u64) -> Result<u64> {
3432 if min == max {
3433 return Ok(min);
3434 }
3435 let x = {
3436 let min = min as f64;
3437 let max = max as f64;
3438 let max_inbounds = max_inbounds as f64;
3439 let x = u.arbitrary::<u32>()?;
3440 let x = f64::from(x);
3441 let x = map_custom(
3442 x,
3443 f64::from(u32::MIN)..f64::from(u32::MAX),
3444 min..max_inbounds,
3445 min..max,
3446 );
3447 assert!(min <= x, "{min} <= {x}");
3448 assert!(x <= max, "{x} <= {max}");
3449 x.round() as u64
3450 };
3451
3452 return Ok(x.clamp(min, max));
3455
3456 fn map_custom(
3463 value: f64,
3464 input: Range<f64>,
3465 output_inbounds: Range<f64>,
3466 output: Range<f64>,
3467 ) -> f64 {
3468 assert!(!value.is_nan(), "{}", value);
3469 assert!(value.is_finite(), "{}", value);
3470 assert!(input.start < input.end, "{} < {}", input.start, input.end);
3471 assert!(
3472 output.start < output.end,
3473 "{} < {}",
3474 output.start,
3475 output.end
3476 );
3477 assert!(value >= input.start, "{} >= {}", value, input.start);
3478 assert!(value <= input.end, "{} <= {}", value, input.end);
3479 assert!(
3480 output.start <= output_inbounds.start,
3481 "{} <= {}",
3482 output.start,
3483 output_inbounds.start
3484 );
3485 assert!(
3486 output_inbounds.end <= output.end,
3487 "{} <= {}",
3488 output_inbounds.end,
3489 output.end
3490 );
3491
3492 let x = map_linear(value, input, 0.0..1.0);
3493 let result = if x < PCT_INBOUNDS {
3494 if output_inbounds.start == output_inbounds.end {
3495 output_inbounds.start
3496 } else {
3497 let unscaled = x * x * x * x * x * x;
3498 map_linear(unscaled, 0.0..1.0, output_inbounds)
3499 }
3500 } else {
3501 map_linear(x, 0.0..1.0, output.clone())
3502 };
3503
3504 assert!(result >= output.start, "{} >= {}", result, output.start);
3505 assert!(result <= output.end, "{} <= {}", result, output.end);
3506 result
3507 }
3508
3509 fn map_linear(
3514 value: f64,
3515 Range {
3516 start: in_low,
3517 end: in_high,
3518 }: Range<f64>,
3519 Range {
3520 start: out_low,
3521 end: out_high,
3522 }: Range<f64>,
3523 ) -> f64 {
3524 assert!(!value.is_nan(), "{}", value);
3525 assert!(value.is_finite(), "{}", value);
3526 assert!(in_low < in_high, "{in_low} < {in_high}");
3527 assert!(out_low < out_high, "{out_low} < {out_high}");
3528 assert!(value >= in_low, "{value} >= {in_low}");
3529 assert!(value <= in_high, "{value} <= {in_high}");
3530
3531 let dividend = out_high - out_low;
3532 let divisor = in_high - in_low;
3533 let slope = dividend / divisor;
3534 let result = out_low + (slope * (value - in_low));
3535
3536 assert!(result >= out_low, "{result} >= {out_low}");
3537 assert!(result <= out_high, "{result} <= {out_high}");
3538 result
3539 }
3540}
3541
3542fn arbitrary_offset(
3546 u: &mut Unstructured,
3547 limit_min: u64,
3548 limit_max: u64,
3549 segment_size: usize,
3550) -> Result<u64> {
3551 let size = u64::try_from(segment_size).unwrap();
3552
3553 if size > limit_min {
3556 u.int_in_range(0..=limit_max)
3557 } else {
3558 gradually_grow(u, 0, limit_min - size, limit_max)
3559 }
3560}
3561
3562fn unique_import_strings(max_size: usize, u: &mut Unstructured) -> Result<(String, String)> {
3563 let module = limited_string(max_size, u)?;
3564 let field = limited_string(max_size, u)?;
3565 Ok((module, field))
3566}
3567
3568fn arbitrary_vec_u8(u: &mut Unstructured) -> Result<Vec<u8>> {
3569 let size = u.arbitrary_len::<u8>()?;
3570 Ok(u.bytes(size)?.to_vec())
3571}
3572
3573impl EntityType {
3574 fn size(&self) -> u32 {
3575 match self {
3576 EntityType::Tag(_)
3577 | EntityType::Global(_)
3578 | EntityType::Table(_)
3579 | EntityType::Memory(_) => 1,
3580 EntityType::Func(_, ty) => 1 + (ty.params.len() + ty.results.len()) as u32,
3581 }
3582 }
3583}
3584
3585#[derive(Clone, Copy, Debug, Default)]
3596#[cfg_attr(
3597 feature = "serde",
3598 derive(serde_derive::Deserialize, serde_derive::Serialize)
3599)]
3600pub struct InstructionKinds(pub(crate) FlagSet<InstructionKind>);
3601
3602impl InstructionKinds {
3603 pub fn new(kinds: &[InstructionKind]) -> Self {
3605 Self(kinds.iter().fold(FlagSet::default(), |ks, k| ks | *k))
3606 }
3607
3608 pub fn all() -> Self {
3610 Self(FlagSet::full())
3611 }
3612
3613 pub fn none() -> Self {
3615 Self(FlagSet::default())
3616 }
3617
3618 #[inline]
3620 pub fn contains(&self, kind: InstructionKind) -> bool {
3621 self.0.contains(kind)
3622 }
3623
3624 pub fn without_floats(&self) -> Self {
3626 let mut floatless = self.0;
3627 if floatless.contains(InstructionKind::Numeric) {
3628 floatless -= InstructionKind::Numeric;
3629 floatless |= InstructionKind::NumericInt;
3630 }
3631 if floatless.contains(InstructionKind::Vector) {
3632 floatless -= InstructionKind::Vector;
3633 floatless |= InstructionKind::VectorInt;
3634 }
3635 if floatless.contains(InstructionKind::Memory) {
3636 floatless -= InstructionKind::Memory;
3637 floatless |= InstructionKind::MemoryInt;
3638 }
3639 Self(floatless)
3640 }
3641}
3642
3643flags! {
3644 #[allow(missing_docs)]
3647 #[cfg_attr(feature = "_internal_cli", derive(serde_derive::Deserialize))]
3648 pub enum InstructionKind: u16 {
3649 NumericInt = 1 << 0,
3650 Numeric = (1 << 1) | (1 << 0),
3651 VectorInt = 1 << 2,
3652 Vector = (1 << 3) | (1 << 2),
3653 Reference = 1 << 4,
3654 Parametric = 1 << 5,
3655 Variable = 1 << 6,
3656 Table = 1 << 7,
3657 MemoryInt = 1 << 8,
3658 Memory = (1 << 9) | (1 << 8),
3659 Control = 1 << 10,
3660 Aggregate = 1 << 11,
3661 }
3662}
3663
3664impl FromStr for InstructionKinds {
3665 type Err = String;
3666 fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
3667 let mut kinds = vec![];
3668 for part in s.split(",") {
3669 let kind = InstructionKind::from_str(part)?;
3670 kinds.push(kind);
3671 }
3672 Ok(InstructionKinds::new(&kinds))
3673 }
3674}
3675
3676impl FromStr for InstructionKind {
3677 type Err = String;
3678 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
3679 match s.to_lowercase().as_str() {
3680 "numeric_non_float" => Ok(InstructionKind::NumericInt),
3681 "numeric" => Ok(InstructionKind::Numeric),
3682 "vector_non_float" => Ok(InstructionKind::VectorInt),
3683 "vector" => Ok(InstructionKind::Vector),
3684 "reference" => Ok(InstructionKind::Reference),
3685 "parametric" => Ok(InstructionKind::Parametric),
3686 "variable" => Ok(InstructionKind::Variable),
3687 "table" => Ok(InstructionKind::Table),
3688 "memory_non_float" => Ok(InstructionKind::MemoryInt),
3689 "memory" => Ok(InstructionKind::Memory),
3690 "control" => Ok(InstructionKind::Control),
3691 "aggregate" => Ok(InstructionKind::Aggregate),
3692 _ => Err(format!("unknown instruction kind: {s}")),
3693 }
3694 }
3695}
3696
3697#[cfg(feature = "wasmparser")]
3700impl TryFrom<wasmparser::FuncType> for FuncType {
3701 type Error = ();
3702
3703 fn try_from(value: wasmparser::FuncType) -> Result<Self, Self::Error> {
3704 Ok(FuncType {
3705 params: value
3706 .params()
3707 .iter()
3708 .copied()
3709 .map(|ty| ty.try_into().map_err(|_| ()))
3710 .collect::<Result<Vec<_>, _>>()?,
3711 results: value
3712 .results()
3713 .iter()
3714 .copied()
3715 .map(|ty| ty.try_into().map_err(|_| ()))
3716 .collect::<Result<Vec<_>, _>>()?,
3717 })
3718 }
3719}
3720
3721#[cfg(feature = "wasmparser")]
3722impl TryFrom<wasmparser::CompositeType> for CompositeType {
3723 type Error = ();
3724
3725 fn try_from(value: wasmparser::CompositeType) -> Result<Self, Self::Error> {
3726 let inner_type = match value.inner {
3727 wasmparser::CompositeInnerType::Func(func_type) => {
3728 CompositeInnerType::Func(Rc::new(func_type.try_into()?))
3729 }
3730 wasmparser::CompositeInnerType::Array(array_type) => {
3731 CompositeInnerType::Array(array_type.try_into().map_err(|_| ())?)
3732 }
3733 wasmparser::CompositeInnerType::Struct(struct_type) => {
3734 CompositeInnerType::Struct(struct_type.try_into().map_err(|_| ())?)
3735 }
3736 wasmparser::CompositeInnerType::Cont(_) => {
3737 panic!("continuation type is not supported by wasm-smith currently.")
3738 }
3739 };
3740
3741 Ok(CompositeType {
3742 inner: inner_type,
3743 shared: value.shared,
3744 descriptor: value
3745 .descriptor_idx
3746 .map(|idx| idx.as_module_index().ok_or(()))
3747 .transpose()?,
3748 describes: value
3749 .describes_idx
3750 .map(|idx| idx.as_module_index().ok_or(()))
3751 .transpose()?,
3752 })
3753 }
3754}
3755
3756#[cfg(feature = "wasmparser")]
3757impl TryFrom<wasmparser::SubType> for SubType {
3758 type Error = ();
3759
3760 fn try_from(value: wasmparser::SubType) -> Result<Self, Self::Error> {
3761 Ok(SubType {
3762 is_final: value.is_final,
3763 supertype: value
3764 .supertype_idx
3765 .map(|idx| idx.as_module_index().ok_or(()))
3766 .transpose()?,
3767 composite_type: value.composite_type.try_into()?,
3768 depth: 1,
3771 })
3772 }
3773}