1mod code_builder;
4pub(crate) mod encode;
5mod terminate;
6
7use crate::{arbitrary_loop, limited_string, unique_string, Config};
8use arbitrary::{Arbitrary, Result, Unstructured};
9use code_builder::CodeBuilderAllocations;
10use flagset::{flags, FlagSet};
11use std::collections::{HashMap, HashSet};
12use std::fmt;
13use std::mem;
14use std::ops::Range;
15use std::rc::Rc;
16use std::str::{self, FromStr};
17use wasm_encoder::{
18 AbstractHeapType, ArrayType, BlockType, ConstExpr, ExportKind, FieldType, HeapType, RefType,
19 StorageType, StructType, ValType,
20};
21pub(crate) use wasm_encoder::{GlobalType, MemoryType, TableType};
22
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 const_expr_choices: Vec<Box<dyn Fn(&mut Unstructured, ValType) -> Result<ConstExpr>>>,
150
151 max_type_limit: MaxTypeLimit,
153
154 interesting_values32: Vec<u32>,
157 interesting_values64: Vec<u64>,
158}
159
160impl<'a> Arbitrary<'a> for Module {
161 fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
162 Module::new(Config::default(), u)
163 }
164}
165
166impl fmt::Debug for Module {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 f.debug_struct("Module")
169 .field("config", &self.config)
170 .field(&"...", &"...")
171 .finish()
172 }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176pub(crate) enum DuplicateImportsBehavior {
177 Allowed,
178 Disallowed,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182enum AllowEmptyRecGroup {
183 Yes,
184 No,
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq)]
188enum MaxTypeLimit {
189 ModuleTypes,
190 Num(u32),
191}
192
193impl Module {
194 pub fn config(&self) -> &Config {
196 &self.config
197 }
198
199 pub fn new(config: Config, u: &mut Unstructured<'_>) -> Result<Self> {
202 Self::new_internal(config, u, DuplicateImportsBehavior::Allowed)
203 }
204
205 pub(crate) fn new_internal(
206 config: Config,
207 u: &mut Unstructured<'_>,
208 duplicate_imports_behavior: DuplicateImportsBehavior,
209 ) -> Result<Self> {
210 let mut module = Module::empty(config, duplicate_imports_behavior);
211 module.build(u)?;
212 Ok(module)
213 }
214
215 fn empty(mut config: Config, duplicate_imports_behavior: DuplicateImportsBehavior) -> Self {
216 config.sanitize();
217 Module {
218 config,
219 duplicate_imports_behavior,
220 valtypes: Vec::new(),
221 types: Vec::new(),
222 rec_groups: Vec::new(),
223 can_subtype: Vec::new(),
224 super_to_sub_types: HashMap::new(),
225 should_encode_types: false,
226 imports: Vec::new(),
227 should_encode_imports: false,
228 array_types: Vec::new(),
229 func_types: Vec::new(),
230 struct_types: Vec::new(),
231 num_imports: 0,
232 num_defined_tags: 0,
233 num_defined_funcs: 0,
234 defined_tables: Vec::new(),
235 num_defined_memories: 0,
236 defined_globals: Vec::new(),
237 tags: Vec::new(),
238 funcs: Vec::new(),
239 tables: Vec::new(),
240 globals: Vec::new(),
241 memories: Vec::new(),
242 exports: Vec::new(),
243 start: None,
244 elems: Vec::new(),
245 code: Vec::new(),
246 data: Vec::new(),
247 type_size: 0,
248 export_names: HashSet::new(),
249 const_expr_choices: Vec::new(),
250 max_type_limit: MaxTypeLimit::ModuleTypes,
251 interesting_values32: Vec::new(),
252 interesting_values64: Vec::new(),
253 must_share: false,
254 }
255 }
256}
257
258#[derive(Clone, Debug, PartialEq, Eq, Hash)]
259pub(crate) struct SubType {
260 pub(crate) is_final: bool,
261 pub(crate) supertype: Option<u32>,
262 pub(crate) composite_type: CompositeType,
263}
264
265impl SubType {
266 fn unwrap_struct(&self) -> &StructType {
267 self.composite_type.unwrap_struct()
268 }
269
270 fn unwrap_func(&self) -> &Rc<FuncType> {
271 self.composite_type.unwrap_func()
272 }
273
274 fn unwrap_array(&self) -> &ArrayType {
275 self.composite_type.unwrap_array()
276 }
277}
278
279#[derive(Clone, Debug, PartialEq, Eq, Hash)]
280pub(crate) struct CompositeType {
281 pub inner: CompositeInnerType,
282 pub shared: bool,
283}
284
285impl CompositeType {
286 #[cfg(any(feature = "component-model", feature = "wasmparser"))]
287 pub(crate) fn new_func(func: Rc<FuncType>, shared: bool) -> Self {
288 Self {
289 inner: CompositeInnerType::Func(func),
290 shared,
291 }
292 }
293
294 fn unwrap_func(&self) -> &Rc<FuncType> {
295 match &self.inner {
296 CompositeInnerType::Func(f) => f,
297 _ => panic!("not a func"),
298 }
299 }
300
301 fn unwrap_array(&self) -> &ArrayType {
302 match &self.inner {
303 CompositeInnerType::Array(a) => a,
304 _ => panic!("not an array"),
305 }
306 }
307
308 fn unwrap_struct(&self) -> &StructType {
309 match &self.inner {
310 CompositeInnerType::Struct(s) => s,
311 _ => panic!("not a struct"),
312 }
313 }
314}
315
316impl From<&CompositeType> for wasm_encoder::CompositeType {
317 fn from(ty: &CompositeType) -> Self {
318 let inner = match &ty.inner {
319 CompositeInnerType::Array(a) => wasm_encoder::CompositeInnerType::Array(*a),
320 CompositeInnerType::Func(f) => wasm_encoder::CompositeInnerType::Func(
321 wasm_encoder::FuncType::new(f.params.iter().cloned(), f.results.iter().cloned()),
322 ),
323 CompositeInnerType::Struct(s) => wasm_encoder::CompositeInnerType::Struct(s.clone()),
324 };
325 wasm_encoder::CompositeType {
326 shared: ty.shared,
327 inner,
328 }
329 }
330}
331
332#[derive(Clone, Debug, PartialEq, Eq, Hash)]
333pub(crate) enum CompositeInnerType {
334 Array(ArrayType),
335 Func(Rc<FuncType>),
336 Struct(StructType),
337}
338
339#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
341pub(crate) struct FuncType {
342 pub(crate) params: Vec<ValType>,
344 pub(crate) results: Vec<ValType>,
346}
347
348#[derive(Clone, Debug, PartialEq, Eq, Hash)]
350pub(crate) struct Import {
351 pub(crate) module: String,
353 pub(crate) field: String,
355 pub(crate) entity_type: EntityType,
357}
358
359#[derive(Clone, Debug, PartialEq, Eq, Hash)]
361pub(crate) enum EntityType {
362 Global(GlobalType),
364 Table(TableType),
366 Memory(MemoryType),
368 Tag(TagType),
370 Func(u32, Rc<FuncType>),
372}
373
374#[derive(Clone, Debug, PartialEq, Eq, Hash)]
376pub(crate) struct TagType {
377 func_type_idx: u32,
379 func_type: Rc<FuncType>,
381}
382
383#[derive(Debug)]
384struct ElementSegment {
385 kind: ElementKind,
386 ty: RefType,
387 items: Elements,
388}
389
390#[derive(Debug)]
391enum ElementKind {
392 Passive,
393 Declared,
394 Active {
395 table: Option<u32>, offset: Offset,
397 },
398}
399
400#[derive(Debug)]
401enum Elements {
402 Functions(Vec<u32>),
403 Expressions(Vec<ConstExpr>),
404}
405
406#[derive(Debug)]
407struct Code {
408 locals: Vec<ValType>,
409 instructions: Instructions,
410}
411
412#[derive(Debug)]
413enum Instructions {
414 Generated(Vec<Instruction>),
415 Arbitrary(Vec<u8>),
416}
417
418#[derive(Debug)]
419struct DataSegment {
420 kind: DataSegmentKind,
421 init: Vec<u8>,
422}
423
424#[derive(Debug)]
425enum DataSegmentKind {
426 Passive,
427 Active { memory_index: u32, offset: Offset },
428}
429
430#[derive(Debug)]
431pub(crate) enum Offset {
432 Const32(i32),
433 Const64(i64),
434 Global(u32),
435}
436
437impl Module {
438 fn build(&mut self, u: &mut Unstructured) -> Result<()> {
439 self.valtypes = configured_valtypes(&self.config);
440
441 if self.arbitrary_imports_from_available(u)? {
447 self.arbitrary_types(u)?;
448 } else {
449 self.arbitrary_types(u)?;
450 self.arbitrary_imports(u)?;
451 }
452
453 self.should_encode_imports = !self.imports.is_empty() || u.arbitrary()?;
454
455 self.arbitrary_tags(u)?;
456 self.arbitrary_funcs(u)?;
457 self.arbitrary_tables(u)?;
458 self.arbitrary_memories(u)?;
459 self.arbitrary_globals(u)?;
460 if !self.required_exports(u)? {
461 self.arbitrary_exports(u)?;
462 };
463 self.should_encode_types = !self.types.is_empty() || u.arbitrary()?;
464 self.arbitrary_start(u)?;
465 self.arbitrary_elems(u)?;
466 self.arbitrary_data(u)?;
467 self.arbitrary_code(u)?;
468 Ok(())
469 }
470
471 #[inline]
472 fn val_type_is_sub_type(&self, a: ValType, b: ValType) -> bool {
473 match (a, b) {
474 (a, b) if a == b => true,
475 (ValType::Ref(a), ValType::Ref(b)) => self.ref_type_is_sub_type(a, b),
476 _ => false,
477 }
478 }
479
480 fn ref_type_is_sub_type(&self, a: RefType, b: RefType) -> bool {
482 if a == b {
483 return true;
484 }
485
486 if a.nullable && !b.nullable {
487 return false;
488 }
489
490 self.heap_type_is_sub_type(a.heap_type, b.heap_type)
491 }
492
493 fn heap_type_is_sub_type(&self, a: HeapType, b: HeapType) -> bool {
494 use AbstractHeapType::*;
495 use CompositeInnerType as CT;
496 use HeapType as HT;
497 match (a, b) {
498 (a, b) if a == b => true,
499
500 (
501 HT::Abstract {
502 shared: a_shared,
503 ty: a_ty,
504 },
505 HT::Abstract {
506 shared: b_shared,
507 ty: b_ty,
508 },
509 ) => {
510 a_shared == b_shared
511 && match (a_ty, b_ty) {
512 (Eq | I31 | Struct | Array | None, Any) => true,
513 (I31 | Struct | Array | None, Eq) => true,
514 (NoExtern, Extern) => true,
515 (NoFunc, Func) => true,
516 (None, I31 | Array | Struct) => true,
517 (NoExn, Exn) => true,
518 _ => false,
519 }
520 }
521
522 (HT::Concrete(a), HT::Abstract { shared, ty }) => {
523 let a_ty = &self.ty(a).composite_type;
524 if a_ty.shared != shared {
525 return false;
526 }
527 match ty {
528 Eq | Any => matches!(a_ty.inner, CT::Array(_) | CT::Struct(_)),
529 Struct => matches!(a_ty.inner, CT::Struct(_)),
530 Array => matches!(a_ty.inner, CT::Array(_)),
531 Func => matches!(a_ty.inner, CT::Func(_)),
532 _ => false,
533 }
534 }
535
536 (HT::Abstract { shared, ty }, HT::Concrete(b)) => {
537 let b_ty = &self.ty(b).composite_type;
538 if shared != b_ty.shared {
539 return false;
540 }
541 match ty {
542 None => matches!(b_ty.inner, CT::Array(_) | CT::Struct(_)),
543 NoFunc => matches!(b_ty.inner, CT::Func(_)),
544 _ => false,
545 }
546 }
547
548 (HT::Concrete(mut a), HT::Concrete(b)) => loop {
549 if a == b {
550 return true;
551 }
552 if let Some(supertype) = self.ty(a).supertype {
553 a = supertype;
554 } else {
555 return false;
556 }
557 },
558 }
559 }
560
561 fn arbitrary_types(&mut self, u: &mut Unstructured) -> Result<()> {
562 assert!(self.config.min_types <= self.config.max_types);
563 while self.types.len() < self.config.min_types {
564 self.arbitrary_rec_group(u, AllowEmptyRecGroup::No)?;
565 }
566 while self.types.len() < self.config.max_types {
567 let keep_going = u.arbitrary().unwrap_or(false);
568 if !keep_going {
569 break;
570 }
571 self.arbitrary_rec_group(u, AllowEmptyRecGroup::Yes)?;
572 }
573 Ok(())
574 }
575
576 fn add_type(&mut self, ty: SubType) -> u32 {
577 let index = u32::try_from(self.types.len()).unwrap();
578
579 if let Some(supertype) = ty.supertype {
580 assert_eq!(self.is_shared_type(supertype), ty.composite_type.shared);
581 self.super_to_sub_types
582 .entry(supertype)
583 .or_default()
584 .push(index);
585 }
586
587 let list = match &ty.composite_type.inner {
588 CompositeInnerType::Array(_) => &mut self.array_types,
589 CompositeInnerType::Func(_) => &mut self.func_types,
590 CompositeInnerType::Struct(_) => &mut self.struct_types,
591 };
592 list.push(index);
593
594 if !ty.is_final {
595 self.can_subtype.push(index);
596 }
597
598 self.types.push(ty);
599 index
600 }
601
602 fn arbitrary_rec_group(
603 &mut self,
604 u: &mut Unstructured,
605 kind: AllowEmptyRecGroup,
606 ) -> Result<()> {
607 let rec_group_start = self.types.len();
608
609 assert!(matches!(self.max_type_limit, MaxTypeLimit::ModuleTypes));
610
611 if self.config.gc_enabled {
612 if self.rec_groups.len() > 0 && u.ratio(1, u8::MAX)? {
614 return self.clone_rec_group(u, kind);
615 }
616
617 let max_rec_group_size = self.config.max_types - self.types.len();
619 let min_rec_group_size = match kind {
620 AllowEmptyRecGroup::Yes => 0,
621 AllowEmptyRecGroup::No => 1,
622 };
623 let rec_group_size = u.int_in_range(min_rec_group_size..=max_rec_group_size)?;
624 let type_ref_limit = u32::try_from(self.types.len() + rec_group_size).unwrap();
625 self.max_type_limit = MaxTypeLimit::Num(type_ref_limit);
626 for _ in 0..rec_group_size {
627 let ty = self.arbitrary_sub_type(u)?;
628 self.add_type(ty);
629 }
630 } else {
631 let type_ref_limit = u32::try_from(self.types.len()).unwrap();
632 self.max_type_limit = MaxTypeLimit::Num(type_ref_limit);
633 let ty = self.arbitrary_sub_type(u)?;
634 self.add_type(ty);
635 }
636
637 self.max_type_limit = MaxTypeLimit::ModuleTypes;
638
639 self.rec_groups.push(rec_group_start..self.types.len());
640 Ok(())
641 }
642
643 fn clone_rec_group(&mut self, u: &mut Unstructured, kind: AllowEmptyRecGroup) -> Result<()> {
644 let group = u.choose(&self.rec_groups)?.clone();
649 if group.is_empty() && kind == AllowEmptyRecGroup::No {
650 return Ok(());
651 }
652 if group.len() > self.config.max_types.saturating_sub(self.types.len()) {
653 return Ok(());
654 }
655
656 let new_rec_group_start = self.types.len();
664 for index in group {
665 let orig_ty_index = u32::try_from(index).unwrap();
666 let ty = self.ty(orig_ty_index).clone();
667 self.add_type(ty);
668 }
669 self.rec_groups.push(new_rec_group_start..self.types.len());
670 Ok(())
671 }
672
673 fn arbitrary_sub_type(&mut self, u: &mut Unstructured) -> Result<SubType> {
674 if !self.config.gc_enabled {
675 let shared = self.arbitrary_shared(u)?;
676 let func_type = self.propagate_shared(shared, |m| m.arbitrary_func_type(u))?;
677 let composite_type = CompositeType {
678 inner: CompositeInnerType::Func(func_type),
679 shared,
680 };
681 return Ok(SubType {
682 is_final: true,
683 supertype: None,
684 composite_type,
685 });
686 }
687
688 if !self.can_subtype.is_empty() && u.ratio(1, 32_u8)? {
689 self.arbitrary_sub_type_of_super_type(u)
690 } else {
691 Ok(SubType {
692 is_final: u.arbitrary()?,
693 supertype: None,
694 composite_type: self.arbitrary_composite_type(u)?,
695 })
696 }
697 }
698
699 fn arbitrary_sub_type_of_super_type(&mut self, u: &mut Unstructured) -> Result<SubType> {
700 let supertype = *u.choose(&self.can_subtype)?;
701 let mut composite_type = self.types[usize::try_from(supertype).unwrap()]
702 .composite_type
703 .clone();
704 match &mut composite_type.inner {
705 CompositeInnerType::Array(a) => {
706 a.0 = self.arbitrary_matching_field_type(u, a.0)?;
707 }
708 CompositeInnerType::Func(f) => {
709 *f = self.arbitrary_matching_func_type(u, f)?;
710 }
711 CompositeInnerType::Struct(s) => {
712 *s = self.propagate_shared(composite_type.shared, |m| {
713 m.arbitrary_matching_struct_type(u, s)
714 })?;
715 }
716 }
717 Ok(SubType {
718 is_final: u.arbitrary()?,
719 supertype: Some(supertype),
720 composite_type,
721 })
722 }
723
724 fn arbitrary_matching_struct_type(
725 &mut self,
726 u: &mut Unstructured,
727 ty: &StructType,
728 ) -> Result<StructType> {
729 let len_extra_fields = u.int_in_range(0..=5)?;
730 let mut fields = Vec::with_capacity(ty.fields.len() + len_extra_fields);
731 for field in ty.fields.iter() {
732 fields.push(self.arbitrary_matching_field_type(u, *field)?);
733 }
734 for _ in 0..len_extra_fields {
735 fields.push(self.arbitrary_field_type(u)?);
736 }
737 Ok(StructType {
738 fields: fields.into_boxed_slice(),
739 })
740 }
741
742 fn arbitrary_matching_field_type(
743 &mut self,
744 u: &mut Unstructured,
745 ty: FieldType,
746 ) -> Result<FieldType> {
747 if ty.mutable {
748 Ok(ty)
749 } else {
750 Ok(FieldType {
751 element_type: self.arbitrary_matching_storage_type(u, ty.element_type)?,
752 mutable: false,
753 })
754 }
755 }
756
757 fn arbitrary_matching_storage_type(
758 &mut self,
759 u: &mut Unstructured,
760 ty: StorageType,
761 ) -> Result<StorageType> {
762 match ty {
763 StorageType::I8 => Ok(StorageType::I8),
764 StorageType::I16 => Ok(StorageType::I16),
765 StorageType::Val(ty) => Ok(StorageType::Val(self.arbitrary_matching_val_type(u, ty)?)),
766 }
767 }
768
769 fn arbitrary_matching_val_type(
770 &mut self,
771 u: &mut Unstructured,
772 ty: ValType,
773 ) -> Result<ValType> {
774 match ty {
775 ValType::I32 => Ok(ValType::I32),
776 ValType::I64 => Ok(ValType::I64),
777 ValType::F32 => Ok(ValType::F32),
778 ValType::F64 => Ok(ValType::F64),
779 ValType::V128 => Ok(ValType::V128),
780 ValType::Ref(ty) => Ok(ValType::Ref(self.arbitrary_matching_ref_type(u, ty)?)),
781 }
782 }
783
784 fn arbitrary_matching_ref_type(&self, u: &mut Unstructured, ty: RefType) -> Result<RefType> {
785 Ok(RefType {
786 nullable: ty.nullable,
787 heap_type: self.arbitrary_matching_heap_type(u, ty.heap_type)?,
788 })
789 }
790
791 fn arbitrary_matching_heap_type(&self, u: &mut Unstructured, ty: HeapType) -> Result<HeapType> {
792 use {AbstractHeapType as AHT, CompositeInnerType as CT, HeapType as HT};
793
794 if !self.config.gc_enabled {
795 return Ok(ty);
796 }
797
798 let mut choices = vec![ty];
799 match ty {
800 HT::Abstract { shared, ty } => {
801 use AbstractHeapType::*;
802 let add_abstract = |choices: &mut Vec<HT>, tys: &[AHT]| {
803 choices.extend(tys.iter().map(|&ty| HT::Abstract { shared, ty }));
804 };
805 let add_concrete = |choices: &mut Vec<HT>, tys: &[u32]| {
806 choices.extend(
807 tys.iter()
808 .filter(|&&idx| shared == self.is_shared_type(idx))
809 .copied()
810 .map(HT::Concrete),
811 );
812 };
813 match ty {
814 Any => {
815 add_abstract(&mut choices, &[Eq, Struct, Array, I31, None]);
816 add_concrete(&mut choices, &self.array_types);
817 add_concrete(&mut choices, &self.struct_types);
818 }
819 Eq => {
820 add_abstract(&mut choices, &[Struct, Array, I31, None]);
821 add_concrete(&mut choices, &self.array_types);
822 add_concrete(&mut choices, &self.struct_types);
823 }
824 Struct => {
825 add_abstract(&mut choices, &[Struct, None]);
826 add_concrete(&mut choices, &self.struct_types);
827 }
828 Array => {
829 add_abstract(&mut choices, &[Array, None]);
830 add_concrete(&mut choices, &self.array_types);
831 }
832 I31 => {
833 add_abstract(&mut choices, &[None]);
834 }
835 Func => {
836 add_abstract(&mut choices, &[NoFunc]);
837 add_concrete(&mut choices, &self.func_types);
838 }
839 Extern => {
840 add_abstract(&mut choices, &[NoExtern]);
841 }
842 Exn | NoExn | None | NoExtern | NoFunc | Cont | NoCont => {}
843 }
844 }
845 HT::Concrete(idx) => {
846 if let Some(subs) = self.super_to_sub_types.get(&idx) {
847 choices.extend(subs.iter().copied().map(HT::Concrete));
848 }
849 match self
850 .types
851 .get(usize::try_from(idx).unwrap())
852 .map(|ty| (ty.composite_type.shared, &ty.composite_type.inner))
853 {
854 Some((shared, CT::Array(_) | CT::Struct(_))) => choices.push(HT::Abstract {
855 shared,
856 ty: AbstractHeapType::None,
857 }),
858 Some((shared, CT::Func(_))) => choices.push(HT::Abstract {
859 shared,
860 ty: AbstractHeapType::NoFunc,
861 }),
862 None => {
863 }
869 }
870 }
871 }
872 Ok(*u.choose(&choices)?)
873 }
874
875 fn arbitrary_matching_func_type(
876 &mut self,
877 u: &mut Unstructured,
878 ty: &FuncType,
879 ) -> Result<Rc<FuncType>> {
880 let mut params = Vec::with_capacity(ty.params.len());
884 for param in &ty.params {
885 params.push(self.arbitrary_super_type_of_val_type(u, *param)?);
886 }
887 let mut results = Vec::with_capacity(ty.results.len());
888 for result in &ty.results {
889 results.push(self.arbitrary_matching_val_type(u, *result)?);
890 }
891 Ok(Rc::new(FuncType { params, results }))
892 }
893
894 fn arbitrary_super_type_of_val_type(
895 &mut self,
896 u: &mut Unstructured,
897 ty: ValType,
898 ) -> Result<ValType> {
899 match ty {
900 ValType::I32 => Ok(ValType::I32),
901 ValType::I64 => Ok(ValType::I64),
902 ValType::F32 => Ok(ValType::F32),
903 ValType::F64 => Ok(ValType::F64),
904 ValType::V128 => Ok(ValType::V128),
905 ValType::Ref(ty) => Ok(ValType::Ref(self.arbitrary_super_type_of_ref_type(u, ty)?)),
906 }
907 }
908
909 fn arbitrary_super_type_of_ref_type(
910 &self,
911 u: &mut Unstructured,
912 ty: RefType,
913 ) -> Result<RefType> {
914 Ok(RefType {
915 nullable: true,
922 heap_type: self.arbitrary_super_type_of_heap_type(u, ty.heap_type)?,
923 })
924 }
925
926 fn arbitrary_super_type_of_heap_type(
927 &self,
928 u: &mut Unstructured,
929 ty: HeapType,
930 ) -> Result<HeapType> {
931 use {AbstractHeapType as AHT, CompositeInnerType as CT, HeapType as HT};
932
933 if !self.config.gc_enabled {
934 return Ok(ty);
935 }
936
937 let mut choices = vec![ty];
938 match ty {
939 HT::Abstract { shared, ty } => {
940 use AbstractHeapType::*;
941 let add_abstract = |choices: &mut Vec<HT>, tys: &[AHT]| {
942 choices.extend(tys.iter().map(|&ty| HT::Abstract { shared, ty }));
943 };
944 let add_concrete = |choices: &mut Vec<HT>, tys: &[u32]| {
945 choices.extend(
946 tys.iter()
947 .filter(|&&idx| shared == self.is_shared_type(idx))
948 .copied()
949 .map(HT::Concrete),
950 );
951 };
952 match ty {
953 None => {
954 add_abstract(&mut choices, &[Any, Eq, Struct, Array, I31]);
955 add_concrete(&mut choices, &self.array_types);
956 add_concrete(&mut choices, &self.struct_types);
957 }
958 NoExtern => {
959 add_abstract(&mut choices, &[Extern]);
960 }
961 NoFunc => {
962 add_abstract(&mut choices, &[Func]);
963 add_concrete(&mut choices, &self.func_types);
964 }
965 NoExn => {
966 add_abstract(&mut choices, &[Exn]);
967 }
968 Struct | Array | I31 => {
969 add_abstract(&mut choices, &[Any, Eq]);
970 }
971 Eq => {
972 add_abstract(&mut choices, &[Any]);
973 }
974 NoCont => {
975 add_abstract(&mut choices, &[Cont]);
976 }
977 Exn | Any | Func | Extern | Cont => {}
978 }
979 }
980 HT::Concrete(mut idx) => {
981 if let Some(sub_ty) = &self.types.get(usize::try_from(idx).unwrap()) {
982 use AbstractHeapType::*;
983 let ht = |ty| HT::Abstract {
984 shared: sub_ty.composite_type.shared,
985 ty,
986 };
987 match &sub_ty.composite_type.inner {
988 CT::Array(_) => {
989 choices.extend([ht(Any), ht(Eq), ht(Array)]);
990 }
991 CT::Func(_) => {
992 choices.push(ht(Func));
993 }
994 CT::Struct(_) => {
995 choices.extend([ht(Any), ht(Eq), ht(Struct)]);
996 }
997 }
998 } else {
999 }
1006 while let Some(supertype) = self
1007 .types
1008 .get(usize::try_from(idx).unwrap())
1009 .and_then(|ty| ty.supertype)
1010 {
1011 choices.push(HT::Concrete(supertype));
1012 idx = supertype;
1013 }
1014 }
1015 }
1016 Ok(*u.choose(&choices)?)
1017 }
1018
1019 fn arbitrary_composite_type(&mut self, u: &mut Unstructured) -> Result<CompositeType> {
1020 use CompositeInnerType as CT;
1021 let shared = self.arbitrary_shared(u)?;
1022
1023 if !self.config.gc_enabled {
1024 return Ok(CompositeType {
1025 shared,
1026 inner: CT::Func(self.propagate_shared(shared, |m| m.arbitrary_func_type(u))?),
1027 });
1028 }
1029
1030 match u.int_in_range(0..=2)? {
1031 0 => Ok(CompositeType {
1032 shared,
1033 inner: CT::Array(ArrayType(
1034 self.propagate_shared(shared, |m| m.arbitrary_field_type(u))?,
1035 )),
1036 }),
1037 1 => Ok(CompositeType {
1038 shared,
1039 inner: CT::Func(self.propagate_shared(shared, |m| m.arbitrary_func_type(u))?),
1040 }),
1041 2 => Ok(CompositeType {
1042 shared,
1043 inner: CT::Struct(self.propagate_shared(shared, |m| m.arbitrary_struct_type(u))?),
1044 }),
1045 _ => unreachable!(),
1046 }
1047 }
1048
1049 fn arbitrary_struct_type(&mut self, u: &mut Unstructured) -> Result<StructType> {
1050 let len = u.int_in_range(0..=20)?;
1051 let mut fields = Vec::with_capacity(len);
1052 for _ in 0..len {
1053 fields.push(self.arbitrary_field_type(u)?);
1054 }
1055 Ok(StructType {
1056 fields: fields.into_boxed_slice(),
1057 })
1058 }
1059
1060 fn arbitrary_field_type(&mut self, u: &mut Unstructured) -> Result<FieldType> {
1061 Ok(FieldType {
1062 element_type: self.arbitrary_storage_type(u)?,
1063 mutable: u.arbitrary()?,
1064 })
1065 }
1066
1067 fn arbitrary_storage_type(&mut self, u: &mut Unstructured) -> Result<StorageType> {
1068 match u.int_in_range(0..=2)? {
1069 0 => Ok(StorageType::I8),
1070 1 => Ok(StorageType::I16),
1071 2 => Ok(StorageType::Val(self.arbitrary_valtype(u)?)),
1072 _ => unreachable!(),
1073 }
1074 }
1075
1076 fn arbitrary_ref_type(&self, u: &mut Unstructured) -> Result<RefType> {
1077 if !self.config.reference_types_enabled {
1078 return Ok(RefType::FUNCREF);
1079 }
1080 Ok(RefType {
1081 nullable: true,
1082 heap_type: self.arbitrary_heap_type(u)?,
1083 })
1084 }
1085
1086 fn arbitrary_heap_type(&self, u: &mut Unstructured) -> Result<HeapType> {
1087 assert!(self.config.reference_types_enabled);
1088
1089 let concrete_type_limit = match self.max_type_limit {
1090 MaxTypeLimit::Num(n) => n,
1091 MaxTypeLimit::ModuleTypes => u32::try_from(self.types.len()).unwrap(),
1092 };
1093
1094 if self.config.gc_enabled && concrete_type_limit > 0 && u.arbitrary()? {
1095 let idx = u.int_in_range(0..=concrete_type_limit - 1)?;
1096 if let Some(ty) = self.types.get(idx as usize) {
1102 if !(self.must_share && !ty.composite_type.shared) {
1105 return Ok(HeapType::Concrete(idx));
1106 }
1107 }
1108 }
1109
1110 use AbstractHeapType::*;
1111 let mut choices = vec![Func, Extern];
1112 if self.config.exceptions_enabled {
1113 choices.push(Exn);
1114 }
1115 if self.config.gc_enabled {
1116 choices.extend(
1117 [Any, None, NoExtern, NoFunc, Eq, Struct, Array, I31]
1118 .iter()
1119 .copied(),
1120 );
1121 }
1122
1123 Ok(HeapType::Abstract {
1124 shared: self.arbitrary_shared(u)?,
1125 ty: *u.choose(&choices)?,
1126 })
1127 }
1128
1129 fn arbitrary_func_type(&mut self, u: &mut Unstructured) -> Result<Rc<FuncType>> {
1130 let mut params = vec![];
1131 let mut results = vec![];
1132 let max_params = 20;
1133 arbitrary_loop(u, 0, max_params, |u| {
1134 params.push(self.arbitrary_valtype(u)?);
1135 Ok(true)
1136 })?;
1137 let max_results = if self.config.multi_value_enabled {
1138 max_params
1139 } else {
1140 1
1141 };
1142 arbitrary_loop(u, 0, max_results, |u| {
1143 results.push(self.arbitrary_valtype(u)?);
1144 Ok(true)
1145 })?;
1146 Ok(Rc::new(FuncType { params, results }))
1147 }
1148
1149 fn can_add_local_or_import_tag(&self) -> bool {
1150 self.config.exceptions_enabled
1151 && self.has_tag_func_types()
1152 && self.tags.len() < self.config.max_tags
1153 }
1154
1155 fn can_add_local_or_import_func(&self) -> bool {
1156 !self.func_types.is_empty() && self.funcs.len() < self.config.max_funcs
1157 }
1158
1159 fn can_add_local_or_import_table(&self) -> bool {
1160 self.tables.len() < self.config.max_tables
1161 }
1162
1163 fn can_add_local_or_import_global(&self) -> bool {
1164 self.globals.len() < self.config.max_globals
1165 }
1166
1167 fn can_add_local_or_import_memory(&self) -> bool {
1168 self.memories.len() < self.config.max_memories
1169 }
1170
1171 fn arbitrary_imports(&mut self, u: &mut Unstructured) -> Result<()> {
1172 if self.config.max_type_size < self.type_size {
1173 return Ok(());
1174 }
1175
1176 let mut import_strings = HashSet::new();
1177 let mut choices: Vec<fn(&mut Unstructured, &mut Module) -> Result<EntityType>> =
1178 Vec::with_capacity(5);
1179 let min = self.config.min_imports.saturating_sub(self.num_imports);
1180 let max = self.config.max_imports.saturating_sub(self.num_imports);
1181 arbitrary_loop(u, min, max, |u| {
1182 choices.clear();
1183 if self.can_add_local_or_import_tag() {
1184 choices.push(|u, m| {
1185 let ty = m.arbitrary_tag_type(u)?;
1186 Ok(EntityType::Tag(ty))
1187 });
1188 }
1189 if self.can_add_local_or_import_func() {
1190 choices.push(|u, m| {
1191 let idx = *u.choose(&m.func_types)?;
1192 let ty = m.func_type(idx).clone();
1193 Ok(EntityType::Func(idx, ty))
1194 });
1195 }
1196 if self.can_add_local_or_import_global() {
1197 choices.push(|u, m| {
1198 let ty = m.arbitrary_global_type(u)?;
1199 Ok(EntityType::Global(ty))
1200 });
1201 }
1202 if self.can_add_local_or_import_memory() {
1203 choices.push(|u, m| {
1204 let ty = arbitrary_memtype(u, m.config())?;
1205 Ok(EntityType::Memory(ty))
1206 });
1207 }
1208 if self.can_add_local_or_import_table() {
1209 choices.push(|u, m| {
1210 let ty = arbitrary_table_type(u, m.config(), Some(m))?;
1211 Ok(EntityType::Table(ty))
1212 });
1213 }
1214
1215 if choices.is_empty() {
1216 return Ok(false);
1221 }
1222
1223 let f = u.choose(&choices)?;
1226 let entity_type = f(u, self)?;
1227 let budget = self.config.max_type_size - self.type_size;
1228 if entity_type.size() + 1 > budget {
1229 return Ok(false);
1230 }
1231 self.type_size += entity_type.size() + 1;
1232
1233 let mut import_pair = unique_import_strings(1_000, u)?;
1235 if self.duplicate_imports_behavior == DuplicateImportsBehavior::Disallowed {
1236 while import_strings.contains(&import_pair) {
1237 use std::fmt::Write;
1238 write!(&mut import_pair.1, "{}", import_strings.len()).unwrap();
1239 }
1240 import_strings.insert(import_pair.clone());
1241 }
1242 let (module, field) = import_pair;
1243
1244 match &entity_type {
1247 EntityType::Tag(ty) => self.tags.push(ty.clone()),
1248 EntityType::Func(idx, ty) => self.funcs.push((*idx, ty.clone())),
1249 EntityType::Global(ty) => self.globals.push(*ty),
1250 EntityType::Table(ty) => self.tables.push(*ty),
1251 EntityType::Memory(ty) => self.memories.push(*ty),
1252 }
1253
1254 self.num_imports += 1;
1255 self.imports.push(Import {
1256 module,
1257 field,
1258 entity_type,
1259 });
1260 Ok(true)
1261 })?;
1262
1263 Ok(())
1264 }
1265
1266 fn arbitrary_imports_from_available(&mut self, u: &mut Unstructured) -> Result<bool> {
1272 let example_module = if let Some(wasm) = self.config.available_imports.take() {
1273 wasm
1274 } else {
1275 return Ok(false);
1276 };
1277
1278 #[cfg(feature = "wasmparser")]
1279 {
1280 self._arbitrary_imports_from_available(u, &example_module)?;
1281 Ok(true)
1282 }
1283 #[cfg(not(feature = "wasmparser"))]
1284 {
1285 let _ = (example_module, u);
1286 panic!("support for `available_imports` was disabled at compile time");
1287 }
1288 }
1289
1290 #[cfg(feature = "wasmparser")]
1291 fn _arbitrary_imports_from_available(
1292 &mut self,
1293 u: &mut Unstructured,
1294 example_module: &[u8],
1295 ) -> Result<()> {
1296 let mut available_types = Vec::new();
1304 let mut available_imports = Vec::<wasmparser::Import>::new();
1305 for payload in wasmparser::Parser::new(0).parse_all(&example_module) {
1306 match payload.expect("could not parse the available import payload") {
1307 wasmparser::Payload::TypeSection(type_reader) => {
1308 for ty in type_reader.into_iter_err_on_gc_types() {
1309 let ty = ty.expect("could not parse type section");
1310 available_types.push((ty, None));
1311 }
1312 }
1313 wasmparser::Payload::ImportSection(import_reader) => {
1314 for im in import_reader {
1315 let im = im.expect("could not read import");
1316 let use_import = u.arbitrary().unwrap_or(false);
1319 if !use_import {
1320 continue;
1321 }
1322 available_imports.push(im);
1323 }
1324 }
1325 _ => {}
1326 }
1327 }
1328
1329 let max_types = self.config.max_types;
1332 let multi_value_enabled = self.config.multi_value_enabled;
1333 let mut new_imports = Vec::with_capacity(available_imports.len());
1334 let first_type_index = self.types.len();
1335 let mut new_types = Vec::<SubType>::new();
1336
1337 let mut make_func_type = |module: &Self, parsed_sig_idx: u32| {
1340 let serialized_sig_idx = match available_types.get_mut(parsed_sig_idx as usize) {
1341 None => panic!("signature index refers to a type out of bounds"),
1342 Some((_, Some(idx))) => *idx as usize,
1343 Some((func_type, index_store)) => {
1344 let multi_value_required = func_type.results().len() > 1;
1345 let new_index = first_type_index + new_types.len();
1346 if new_index >= max_types || (multi_value_required && !multi_value_enabled) {
1347 return None;
1348 }
1349 let func_type = Rc::new(FuncType {
1350 params: func_type
1351 .params()
1352 .iter()
1353 .map(|t| (*t).try_into().unwrap())
1354 .collect(),
1355 results: func_type
1356 .results()
1357 .iter()
1358 .map(|t| (*t).try_into().unwrap())
1359 .collect(),
1360 });
1361 index_store.replace(new_index as u32);
1362 let shared = module.arbitrary_shared(u).ok()?;
1363 new_types.push(SubType {
1364 is_final: true,
1365 supertype: None,
1366 composite_type: CompositeType::new_func(Rc::clone(&func_type), shared),
1367 });
1368 new_index
1369 }
1370 };
1371 match &new_types[serialized_sig_idx - first_type_index]
1372 .composite_type
1373 .inner
1374 {
1375 CompositeInnerType::Func(f) => Some((serialized_sig_idx as u32, Rc::clone(f))),
1376 _ => unimplemented!(),
1377 }
1378 };
1379
1380 for import in available_imports {
1381 let type_size_budget = self.config.max_type_size - self.type_size;
1382 let entity_type = match &import.ty {
1383 wasmparser::TypeRef::Func(sig_idx) => {
1384 if self.funcs.len() >= self.config.max_funcs {
1385 continue;
1386 } else if let Some((sig_idx, func_type)) = make_func_type(&self, *sig_idx) {
1387 let entity = EntityType::Func(sig_idx as u32, Rc::clone(&func_type));
1388 if type_size_budget < entity.size() {
1389 continue;
1390 }
1391 self.funcs.push((sig_idx, func_type));
1392 entity
1393 } else {
1394 continue;
1395 }
1396 }
1397
1398 wasmparser::TypeRef::Tag(wasmparser::TagType { func_type_idx, .. }) => {
1399 let can_add_tag = self.tags.len() < self.config.max_tags;
1400 if !self.config.exceptions_enabled || !can_add_tag {
1401 continue;
1402 } else if let Some((sig_idx, func_type)) = make_func_type(&self, *func_type_idx)
1403 {
1404 let tag_type = TagType {
1405 func_type_idx: sig_idx,
1406 func_type,
1407 };
1408 let entity = EntityType::Tag(tag_type.clone());
1409 if type_size_budget < entity.size() {
1410 continue;
1411 }
1412 self.tags.push(tag_type);
1413 entity
1414 } else {
1415 continue;
1416 }
1417 }
1418
1419 wasmparser::TypeRef::Table(table_ty) => {
1420 let table_ty = TableType::try_from(*table_ty).unwrap();
1421 let entity = EntityType::Table(table_ty);
1422 let type_size = entity.size();
1423 if type_size_budget < type_size || !self.can_add_local_or_import_table() {
1424 continue;
1425 }
1426 self.type_size += type_size;
1427 self.tables.push(table_ty);
1428 entity
1429 }
1430
1431 wasmparser::TypeRef::Memory(memory_ty) => {
1432 let memory_ty = MemoryType::try_from(*memory_ty).unwrap();
1433 let entity = EntityType::Memory(memory_ty);
1434 let type_size = entity.size();
1435 if type_size_budget < type_size || !self.can_add_local_or_import_memory() {
1436 continue;
1437 }
1438 self.type_size += type_size;
1439 self.memories.push(memory_ty);
1440 entity
1441 }
1442
1443 wasmparser::TypeRef::Global(global_ty) => {
1444 let global_ty = (*global_ty).try_into().unwrap();
1445 let entity = EntityType::Global(global_ty);
1446 let type_size = entity.size();
1447 if type_size_budget < type_size || !self.can_add_local_or_import_global() {
1448 continue;
1449 }
1450 self.type_size += type_size;
1451 self.globals.push(global_ty);
1452 entity
1453 }
1454 };
1455 new_imports.push(Import {
1456 module: import.module.to_string(),
1457 field: import.name.to_string(),
1458 entity_type,
1459 });
1460 self.num_imports += 1;
1461 }
1462
1463 for ty in new_types {
1465 self.rec_groups.push(self.types.len()..self.types.len() + 1);
1466 self.add_type(ty);
1467 }
1468 self.imports.extend(new_imports);
1469
1470 Ok(())
1471 }
1472
1473 fn type_of(&self, kind: ExportKind, index: u32) -> EntityType {
1474 match kind {
1475 ExportKind::Global => EntityType::Global(self.globals[index as usize]),
1476 ExportKind::Memory => EntityType::Memory(self.memories[index as usize]),
1477 ExportKind::Table => EntityType::Table(self.tables[index as usize]),
1478 ExportKind::Func => {
1479 let (_idx, ty) = &self.funcs[index as usize];
1480 EntityType::Func(u32::max_value(), ty.clone())
1481 }
1482 ExportKind::Tag => EntityType::Tag(self.tags[index as usize].clone()),
1483 }
1484 }
1485
1486 fn ty(&self, idx: u32) -> &SubType {
1487 &self.types[idx as usize]
1488 }
1489
1490 fn func_types(&self) -> impl Iterator<Item = (u32, &FuncType)> + '_ {
1491 self.func_types
1492 .iter()
1493 .copied()
1494 .map(move |type_i| (type_i, &**self.func_type(type_i)))
1495 }
1496
1497 fn func_type(&self, idx: u32) -> &Rc<FuncType> {
1498 match &self.ty(idx).composite_type.inner {
1499 CompositeInnerType::Func(f) => f,
1500 _ => panic!("types[{idx}] is not a func type"),
1501 }
1502 }
1503
1504 fn tags(&self) -> impl Iterator<Item = (u32, &TagType)> + '_ {
1505 self.tags
1506 .iter()
1507 .enumerate()
1508 .map(move |(i, ty)| (i as u32, ty))
1509 }
1510
1511 fn funcs(&self) -> impl Iterator<Item = (u32, &Rc<FuncType>)> + '_ {
1512 self.funcs
1513 .iter()
1514 .enumerate()
1515 .map(move |(i, (_, ty))| (i as u32, ty))
1516 }
1517
1518 fn has_tag_func_types(&self) -> bool {
1519 self.tag_func_types().next().is_some()
1520 }
1521
1522 fn tag_func_types(&self) -> impl Iterator<Item = u32> + '_ {
1523 self.func_types
1524 .iter()
1525 .copied()
1526 .filter(move |i| self.func_type(*i).results.is_empty())
1527 }
1528
1529 fn arbitrary_valtype(&self, u: &mut Unstructured) -> Result<ValType> {
1530 #[derive(PartialEq, Eq, PartialOrd, Ord)]
1531 enum ValTypeClass {
1532 I32,
1533 I64,
1534 F32,
1535 F64,
1536 V128,
1537 Ref,
1538 }
1539
1540 let mut val_classes: Vec<_> = self
1541 .valtypes
1542 .iter()
1543 .map(|vt| match vt {
1544 ValType::I32 => ValTypeClass::I32,
1545 ValType::I64 => ValTypeClass::I64,
1546 ValType::F32 => ValTypeClass::F32,
1547 ValType::F64 => ValTypeClass::F64,
1548 ValType::V128 => ValTypeClass::V128,
1549 ValType::Ref(_) => ValTypeClass::Ref,
1550 })
1551 .collect();
1552 val_classes.sort_unstable();
1553 val_classes.dedup();
1554
1555 match u.choose(&val_classes)? {
1556 ValTypeClass::I32 => Ok(ValType::I32),
1557 ValTypeClass::I64 => Ok(ValType::I64),
1558 ValTypeClass::F32 => Ok(ValType::F32),
1559 ValTypeClass::F64 => Ok(ValType::F64),
1560 ValTypeClass::V128 => Ok(ValType::V128),
1561 ValTypeClass::Ref => Ok(ValType::Ref(self.arbitrary_ref_type(u)?)),
1562 }
1563 }
1564
1565 fn arbitrary_global_type(&self, u: &mut Unstructured) -> Result<GlobalType> {
1566 let val_type = self.arbitrary_valtype(u)?;
1567 let shared = match val_type {
1569 ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {
1570 self.arbitrary_shared(u)?
1571 }
1572 ValType::Ref(r) => self.is_shared_ref_type(r),
1573 };
1574 Ok(GlobalType {
1575 val_type,
1576 mutable: u.arbitrary()?,
1577 shared,
1578 })
1579 }
1580
1581 fn arbitrary_tag_type(&self, u: &mut Unstructured) -> Result<TagType> {
1582 let candidate_func_types: Vec<_> = self.tag_func_types().collect();
1583 arbitrary_tag_type(u, &candidate_func_types, |ty_idx| {
1584 self.func_type(ty_idx).clone()
1585 })
1586 }
1587
1588 fn arbitrary_tags(&mut self, u: &mut Unstructured) -> Result<()> {
1589 if !self.config.exceptions_enabled || !self.has_tag_func_types() {
1590 return Ok(());
1591 }
1592
1593 arbitrary_loop(u, self.config.min_tags, self.config.max_tags, |u| {
1594 if !self.can_add_local_or_import_tag() {
1595 return Ok(false);
1596 }
1597 self.tags.push(self.arbitrary_tag_type(u)?);
1598 self.num_defined_tags += 1;
1599 Ok(true)
1600 })
1601 }
1602
1603 fn arbitrary_funcs(&mut self, u: &mut Unstructured) -> Result<()> {
1604 if self.func_types.is_empty() {
1605 return Ok(());
1606 }
1607
1608 let unshared_func_types: Vec<_> = self
1613 .func_types
1614 .iter()
1615 .copied()
1616 .filter(|&i| !self.is_shared_type(i))
1617 .collect();
1618 if unshared_func_types.is_empty() {
1619 return Ok(());
1620 }
1621
1622 arbitrary_loop(u, self.config.min_funcs, self.config.max_funcs, |u| {
1623 if !self.can_add_local_or_import_func() {
1624 return Ok(false);
1625 }
1626 let max = unshared_func_types.len() - 1;
1627 let ty = unshared_func_types[u.int_in_range(0..=max)?];
1628 self.funcs.push((ty, self.func_type(ty).clone()));
1629 self.num_defined_funcs += 1;
1630 Ok(true)
1631 })
1632 }
1633
1634 fn arbitrary_tables(&mut self, u: &mut Unstructured) -> Result<()> {
1635 arbitrary_loop(
1636 u,
1637 self.config.min_tables as usize,
1638 self.config.max_tables as usize,
1639 |u| {
1640 if !self.can_add_local_or_import_table() {
1641 return Ok(false);
1642 }
1643 let ty = arbitrary_table_type(u, self.config(), Some(self))?;
1644 let init = self.arbitrary_table_init(u, ty.element_type)?;
1645 self.defined_tables.push(init);
1646 self.tables.push(ty);
1647 Ok(true)
1648 },
1649 )
1650 }
1651
1652 fn arbitrary_table_init(
1658 &mut self,
1659 u: &mut Unstructured,
1660 ty: RefType,
1661 ) -> Result<Option<ConstExpr>> {
1662 if !self.config.gc_enabled {
1663 assert!(ty.nullable);
1664 return Ok(None);
1665 }
1666 if ty.nullable && u.arbitrary()? {
1669 return Ok(None);
1670 }
1671 let expr = self.arbitrary_const_expr(ValType::Ref(ty), u)?;
1672 Ok(Some(expr))
1673 }
1674
1675 fn arbitrary_memories(&mut self, u: &mut Unstructured) -> Result<()> {
1676 arbitrary_loop(
1677 u,
1678 self.config.min_memories as usize,
1679 self.config.max_memories as usize,
1680 |u| {
1681 if !self.can_add_local_or_import_memory() {
1682 return Ok(false);
1683 }
1684 self.num_defined_memories += 1;
1685 self.memories.push(arbitrary_memtype(u, self.config())?);
1686 Ok(true)
1687 },
1688 )
1689 }
1690
1691 fn add_arbitrary_global_of_type(
1693 &mut self,
1694 ty: GlobalType,
1695 u: &mut Unstructured,
1696 ) -> Result<u32> {
1697 let expr = self.arbitrary_const_expr(ty.val_type, u)?;
1698 let global_idx = self.globals.len() as u32;
1699 self.globals.push(ty);
1700 self.defined_globals.push((global_idx, expr));
1701 Ok(global_idx)
1702 }
1703
1704 fn arbitrary_const_expr(&mut self, ty: ValType, u: &mut Unstructured) -> Result<ConstExpr> {
1706 let mut choices = mem::take(&mut self.const_expr_choices);
1707 choices.clear();
1708
1709 for i in self.globals_for_const_expr(ty) {
1713 choices.push(Box::new(move |_, _| Ok(ConstExpr::global_get(i))));
1714 }
1715
1716 let ty = self.arbitrary_matching_val_type(u, ty)?;
1720 match ty {
1721 ValType::I32 => {
1722 choices.push(Box::new(|u, _| Ok(ConstExpr::i32_const(u.arbitrary()?))));
1723 if self.config.extended_const_enabled {
1724 choices.push(Box::new(arbitrary_extended_const));
1725 }
1726 }
1727 ValType::I64 => {
1728 choices.push(Box::new(|u, _| Ok(ConstExpr::i64_const(u.arbitrary()?))));
1729 if self.config.extended_const_enabled {
1730 choices.push(Box::new(arbitrary_extended_const));
1731 }
1732 }
1733 ValType::F32 => choices.push(Box::new(|u, _| Ok(ConstExpr::f32_const(u.arbitrary()?)))),
1734 ValType::F64 => choices.push(Box::new(|u, _| Ok(ConstExpr::f64_const(u.arbitrary()?)))),
1735 ValType::V128 => {
1736 choices.push(Box::new(|u, _| Ok(ConstExpr::v128_const(u.arbitrary()?))))
1737 }
1738
1739 ValType::Ref(ty) => {
1740 if ty.nullable {
1741 choices.push(Box::new(move |_, _| Ok(ConstExpr::ref_null(ty.heap_type))));
1742 }
1743
1744 match ty.heap_type {
1745 HeapType::Abstract {
1746 ty: AbstractHeapType::Func,
1747 shared,
1748 } => {
1749 let num_funcs = self
1750 .funcs
1751 .iter()
1752 .filter(|(t, _)| shared == self.is_shared_type(*t))
1753 .count();
1754 if num_funcs > 0 {
1755 let pick = u.int_in_range(0..=num_funcs - 1)?;
1756 let (i, _) = self
1757 .funcs
1758 .iter()
1759 .map(|(t, _)| *t)
1760 .enumerate()
1761 .filter(|(_, t)| shared == self.is_shared_type(*t))
1762 .nth(pick)
1763 .unwrap();
1764 choices.push(Box::new(move |_, _| Ok(ConstExpr::ref_func(i as u32))));
1765 }
1766 }
1767
1768 HeapType::Concrete(ty) => {
1769 for (i, fty) in self.funcs.iter().map(|(t, _)| *t).enumerate() {
1770 if ty != fty {
1771 continue;
1772 }
1773 choices.push(Box::new(move |_, _| Ok(ConstExpr::ref_func(i as u32))));
1774 }
1775 }
1776
1777 _ => {}
1780 }
1781 }
1782 }
1783
1784 let f = u.choose(&choices)?;
1785 let ret = f(u, ty);
1786 self.const_expr_choices = choices;
1787 return ret;
1788
1789 fn arbitrary_extended_const(u: &mut Unstructured<'_>, ty: ValType) -> Result<ConstExpr> {
1797 use wasm_encoder::Instruction::*;
1798
1799 assert!(ty == ValType::I32 || ty == ValType::I64);
1802 let add = if ty == ValType::I32 { I32Add } else { I64Add };
1803 let sub = if ty == ValType::I32 { I32Sub } else { I64Sub };
1804 let mul = if ty == ValType::I32 { I32Mul } else { I64Mul };
1805 let const_: fn(&mut Unstructured<'_>) -> Result<wasm_encoder::Instruction<'static>> =
1806 if ty == ValType::I32 {
1807 |u| u.arbitrary().map(I32Const)
1808 } else {
1809 |u| u.arbitrary().map(I64Const)
1810 };
1811
1812 let mut instrs = Vec::new();
1817 let mut needed = 1;
1818 while needed > 0 {
1819 let choice = if u.is_empty() || instrs.len() > 10 {
1823 0
1824 } else {
1825 u.int_in_range(0..=3)?
1826 };
1827 match choice {
1828 0 => {
1829 instrs.push(const_(u)?);
1830 needed -= 1;
1831 }
1832 1 => {
1833 instrs.push(add.clone());
1834 needed += 1;
1835 }
1836 2 => {
1837 instrs.push(sub.clone());
1838 needed += 1;
1839 }
1840 3 => {
1841 instrs.push(mul.clone());
1842 needed += 1;
1843 }
1844 _ => unreachable!(),
1845 }
1846 }
1847 Ok(ConstExpr::extended(instrs.into_iter().rev()))
1848 }
1849 }
1850
1851 fn arbitrary_globals(&mut self, u: &mut Unstructured) -> Result<()> {
1852 arbitrary_loop(u, self.config.min_globals, self.config.max_globals, |u| {
1853 if !self.can_add_local_or_import_global() {
1854 return Ok(false);
1855 }
1856
1857 let ty = self.arbitrary_global_type(u)?;
1858 self.add_arbitrary_global_of_type(ty, u)?;
1859
1860 Ok(true)
1861 })
1862 }
1863
1864 fn required_exports(&mut self, u: &mut Unstructured) -> Result<bool> {
1865 let example_module = if let Some(wasm) = self.config.exports.clone() {
1866 wasm
1867 } else {
1868 return Ok(false);
1869 };
1870
1871 #[cfg(feature = "wasmparser")]
1872 {
1873 self._required_exports(u, &example_module)?;
1874 Ok(true)
1875 }
1876 #[cfg(not(feature = "wasmparser"))]
1877 {
1878 let _ = (example_module, u);
1879 panic!("support for `exports` was disabled at compile time");
1880 }
1881 }
1882
1883 #[cfg(feature = "wasmparser")]
1884 fn _required_exports(&mut self, u: &mut Unstructured, example_module: &[u8]) -> Result<()> {
1885 let mut required_exports: Vec<wasmparser::Export> = vec![];
1886 let mut validator = wasmparser::Validator::new();
1887 let exports_types = validator
1888 .validate_all(&example_module)
1889 .expect("Failed to validate `exports` Wasm");
1890 for payload in wasmparser::Parser::new(0).parse_all(&example_module) {
1891 match payload.expect("Failed to read `exports` Wasm") {
1892 wasmparser::Payload::ExportSection(export_reader) => {
1893 required_exports = export_reader
1894 .into_iter()
1895 .collect::<Result<_, _>>()
1896 .expect("Failed to read `exports` export section");
1897 }
1898 _ => {}
1899 }
1900 }
1901
1902 let exports_types = exports_types.as_ref();
1904 for export in required_exports {
1905 let new_index = match exports_types
1906 .entity_type_from_export(&export)
1907 .unwrap_or_else(|| {
1908 panic!(
1909 "Unable to get type from export {:?} in `exports` Wasm",
1910 export,
1911 )
1912 }) {
1913 wasmparser::types::EntityType::Func(id) => {
1915 let subtype = exports_types.get(id).unwrap_or_else(|| {
1916 panic!(
1917 "Unable to get subtype for function {:?} in `exports` Wasm",
1918 id
1919 )
1920 });
1921 match &subtype.composite_type.inner {
1922 wasmparser::CompositeInnerType::Func(func_type) => {
1923 assert!(
1924 subtype.is_final,
1925 "Subtype {:?} from `exports` Wasm is not final",
1926 subtype
1927 );
1928 assert!(
1929 subtype.supertype_idx.is_none(),
1930 "Subtype {:?} from `exports` Wasm has non-empty supertype",
1931 subtype
1932 );
1933 let new_type = Rc::new(FuncType {
1934 params: func_type
1935 .params()
1936 .iter()
1937 .copied()
1938 .map(|t| t.try_into().unwrap())
1939 .collect(),
1940 results: func_type
1941 .results()
1942 .iter()
1943 .copied()
1944 .map(|t| t.try_into().unwrap())
1945 .collect(),
1946 });
1947 self.rec_groups.push(self.types.len()..self.types.len() + 1);
1948 let type_index = self.add_type(SubType {
1949 is_final: true,
1950 supertype: None,
1951 composite_type: CompositeType::new_func(
1952 Rc::clone(&new_type),
1953 subtype.composite_type.shared,
1954 ),
1955 });
1956 let func_index = self.funcs.len() as u32;
1957 self.funcs.push((type_index, new_type));
1958 self.num_defined_funcs += 1;
1959 func_index
1960 }
1961 _ => panic!(
1962 "Unable to handle type {:?} from `exports` Wasm",
1963 subtype.composite_type
1964 ),
1965 }
1966 }
1967 wasmparser::types::EntityType::Global(global_type) => {
1969 self.add_arbitrary_global_of_type(global_type.try_into().unwrap(), u)?
1970 }
1971 wasmparser::types::EntityType::Table(_)
1972 | wasmparser::types::EntityType::Memory(_)
1973 | wasmparser::types::EntityType::Tag(_) => {
1974 panic!(
1975 "Config `exports` has an export of type {:?} which cannot yet be handled.",
1976 export.kind
1977 )
1978 }
1979 };
1980 self.exports
1981 .push((export.name.to_string(), export.kind.into(), new_index));
1982 self.export_names.insert(export.name.to_string());
1983 }
1984
1985 Ok(())
1986 }
1987
1988 fn arbitrary_exports(&mut self, u: &mut Unstructured) -> Result<()> {
1989 if self.config.max_type_size < self.type_size && !self.config.export_everything {
1990 return Ok(());
1991 }
1992
1993 let mut choices: Vec<Vec<(ExportKind, u32)>> = Vec::with_capacity(6);
1995 choices.push(
1996 (0..self.funcs.len())
1997 .map(|i| (ExportKind::Func, i as u32))
1998 .collect(),
1999 );
2000 choices.push(
2001 (0..self.tables.len())
2002 .map(|i| (ExportKind::Table, i as u32))
2003 .collect(),
2004 );
2005 choices.push(
2006 (0..self.memories.len())
2007 .map(|i| (ExportKind::Memory, i as u32))
2008 .collect(),
2009 );
2010 choices.push(
2011 (0..self.globals.len())
2012 .map(|i| (ExportKind::Global, i as u32))
2013 .collect(),
2014 );
2015
2016 if self.config.export_everything {
2019 for choices_by_kind in choices {
2020 for (kind, idx) in choices_by_kind {
2021 let name = unique_string(1_000, &mut self.export_names, u)?;
2022 self.add_arbitrary_export(name, kind, idx)?;
2023 }
2024 }
2025 return Ok(());
2026 }
2027
2028 arbitrary_loop(u, self.config.min_exports, self.config.max_exports, |u| {
2029 let max_size = self.config.max_type_size - self.type_size;
2035 for list in choices.iter_mut() {
2036 list.retain(|(kind, idx)| self.type_of(*kind, *idx).size() + 1 < max_size);
2037 }
2038 choices.retain(|list| !list.is_empty());
2039 if choices.is_empty() {
2040 return Ok(false);
2041 }
2042
2043 let name = unique_string(1_000, &mut self.export_names, u)?;
2046 let list = u.choose(&choices)?;
2047 let (kind, idx) = *u.choose(list)?;
2048 self.add_arbitrary_export(name, kind, idx)?;
2049 Ok(true)
2050 })
2051 }
2052
2053 fn add_arbitrary_export(&mut self, name: String, kind: ExportKind, idx: u32) -> Result<()> {
2054 let ty = self.type_of(kind, idx);
2055 self.type_size += 1 + ty.size();
2056 if self.type_size <= self.config.max_type_size {
2057 self.exports.push((name, kind, idx));
2058 Ok(())
2059 } else {
2060 Err(arbitrary::Error::IncorrectFormat)
2064 }
2065 }
2066
2067 fn arbitrary_start(&mut self, u: &mut Unstructured) -> Result<()> {
2068 if !self.config.allow_start_export {
2069 return Ok(());
2070 }
2071
2072 let mut choices = Vec::with_capacity(self.funcs.len() as usize);
2073
2074 for (func_idx, ty) in self.funcs() {
2075 if ty.params.is_empty() && ty.results.is_empty() {
2076 choices.push(func_idx);
2077 }
2078 }
2079
2080 if !choices.is_empty() && u.arbitrary().unwrap_or(false) {
2081 let f = *u.choose(&choices)?;
2082 self.start = Some(f);
2083 }
2084
2085 Ok(())
2086 }
2087
2088 fn arbitrary_elems(&mut self, u: &mut Unstructured) -> Result<()> {
2089 let mut global_i32 = vec![];
2091 let mut global_i64 = vec![];
2092 if !self.config.disallow_traps {
2093 for i in self.globals_for_const_expr(ValType::I32) {
2094 global_i32.push(i);
2095 }
2096 for i in self.globals_for_const_expr(ValType::I64) {
2097 global_i64.push(i);
2098 }
2099 }
2100 let disallow_traps = self.config.disallow_traps;
2101 let arbitrary_active_elem =
2102 |u: &mut Unstructured, min_mem_size: u64, table: Option<u32>, table_ty: &TableType| {
2103 let global_choices = if table_ty.table64 {
2104 &global_i64
2105 } else {
2106 &global_i32
2107 };
2108 let (offset, max_size_hint) = if !global_choices.is_empty() && u.arbitrary()? {
2109 let g = u.choose(&global_choices)?;
2110 (Offset::Global(*g), None)
2111 } else {
2112 let max_mem_size = if disallow_traps {
2113 table_ty.minimum
2114 } else if table_ty.table64 {
2115 u64::MAX
2116 } else {
2117 u64::from(u32::MAX)
2118 };
2119 let offset = arbitrary_offset(u, min_mem_size, max_mem_size, 0)?;
2120 let max_size_hint = if disallow_traps
2121 || (offset <= min_mem_size
2122 && u.int_in_range(0..=CHANCE_OFFSET_INBOUNDS)? != 0)
2123 {
2124 Some(min_mem_size - offset)
2125 } else {
2126 None
2127 };
2128
2129 let offset = if table_ty.table64 {
2130 Offset::Const64(offset as i64)
2131 } else {
2132 Offset::Const32(offset as i32)
2133 };
2134 (offset, max_size_hint)
2135 };
2136 Ok((ElementKind::Active { table, offset }, max_size_hint))
2137 };
2138
2139 type GenElemSegment<'a> =
2143 dyn Fn(&mut Unstructured) -> Result<(ElementKind, Option<u64>)> + 'a;
2144 let mut choices: Vec<Box<GenElemSegment>> = Vec::new();
2145
2146 if self.config.bulk_memory_enabled {
2149 choices.push(Box::new(|_| Ok((ElementKind::Passive, None))));
2150 choices.push(Box::new(|_| Ok((ElementKind::Declared, None))));
2151 }
2152
2153 for (i, ty) in self.tables.iter().enumerate() {
2154 if ty.minimum == 0 && u.int_in_range(0..=CHANCE_SEGMENT_ON_EMPTY)? != 0 {
2159 continue;
2160 }
2161
2162 let minimum = ty.minimum;
2163 let ty = *ty;
2166 if i == 0 && ty.element_type == RefType::FUNCREF {
2167 choices.push(Box::new(move |u| {
2168 arbitrary_active_elem(u, minimum, None, &ty)
2169 }));
2170 }
2171 if self.config.bulk_memory_enabled {
2172 let idx = Some(i as u32);
2173 choices.push(Box::new(move |u| {
2174 arbitrary_active_elem(u, minimum, idx, &ty)
2175 }));
2176 }
2177 }
2178
2179 if choices.is_empty() {
2180 return Ok(());
2181 }
2182
2183 arbitrary_loop(
2184 u,
2185 self.config.min_element_segments,
2186 self.config.max_element_segments,
2187 |u| {
2188 let (kind, max_size_hint) = u.choose(&choices)?(u)?;
2191 let max = max_size_hint
2192 .map(|i| usize::try_from(i).unwrap())
2193 .unwrap_or_else(|| self.config.max_elements);
2194
2195 let ty = match kind {
2199 ElementKind::Passive | ElementKind::Declared => self.arbitrary_ref_type(u)?,
2200 ElementKind::Active { table, .. } => {
2201 let idx = table.unwrap_or(0);
2202 self.arbitrary_matching_ref_type(u, self.tables[idx as usize].element_type)?
2203 }
2204 };
2205
2206 let can_use_function_list = ty == RefType::FUNCREF;
2210 if !self.config.reference_types_enabled {
2211 assert!(can_use_function_list);
2212 }
2213
2214 let mut func_candidates = Vec::new();
2217 if can_use_function_list {
2218 match ty.heap_type {
2219 HeapType::Abstract {
2220 ty: AbstractHeapType::Func,
2221 ..
2222 } => {
2223 func_candidates.extend(0..self.funcs.len() as u32);
2224 }
2225 HeapType::Concrete(ty) => {
2226 for (i, (fty, _)) in self.funcs.iter().enumerate() {
2227 if *fty == ty {
2228 func_candidates.push(i as u32);
2229 }
2230 }
2231 }
2232 _ => {}
2233 }
2234 }
2235
2236 let items = if !self.config.reference_types_enabled
2241 || (can_use_function_list && u.arbitrary()?)
2242 {
2243 let mut init = vec![];
2244 if func_candidates.len() > 0 {
2245 arbitrary_loop(u, self.config.min_elements, max, |u| {
2246 let func_idx = *u.choose(&func_candidates)?;
2247 init.push(func_idx);
2248 Ok(true)
2249 })?;
2250 }
2251 Elements::Functions(init)
2252 } else {
2253 let mut init = vec![];
2254 arbitrary_loop(u, self.config.min_elements, max, |u| {
2255 init.push(self.arbitrary_const_expr(ValType::Ref(ty), u)?);
2256 Ok(true)
2257 })?;
2258 Elements::Expressions(init)
2259 };
2260
2261 self.elems.push(ElementSegment { kind, ty, items });
2262 Ok(true)
2263 },
2264 )
2265 }
2266
2267 fn arbitrary_code(&mut self, u: &mut Unstructured) -> Result<()> {
2268 self.compute_interesting_values();
2269
2270 self.code.reserve(self.num_defined_funcs);
2271 let mut allocs = CodeBuilderAllocations::new(self, self.config.exports.is_some());
2272 for (idx, ty) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() {
2273 let shared = self.is_shared_type(*idx);
2274 let body = self.arbitrary_func_body(u, ty, &mut allocs, shared)?;
2275 self.code.push(body);
2276 }
2277 allocs.finish(u, self)?;
2278 Ok(())
2279 }
2280
2281 fn arbitrary_func_body(
2282 &self,
2283 u: &mut Unstructured,
2284 ty: &FuncType,
2285 allocs: &mut CodeBuilderAllocations,
2286 shared: bool,
2287 ) -> Result<Code> {
2288 let mut locals = self.arbitrary_locals(u)?;
2289 let builder = allocs.builder(ty, &mut locals, shared);
2290 let instructions = if self.config.allow_invalid_funcs && u.arbitrary().unwrap_or(false) {
2291 Instructions::Arbitrary(arbitrary_vec_u8(u)?)
2292 } else {
2293 Instructions::Generated(builder.arbitrary(u, self)?)
2294 };
2295
2296 Ok(Code {
2297 locals,
2298 instructions,
2299 })
2300 }
2301
2302 fn arbitrary_locals(&self, u: &mut Unstructured) -> Result<Vec<ValType>> {
2303 let mut ret = Vec::new();
2304 arbitrary_loop(u, 0, 100, |u| {
2305 ret.push(self.arbitrary_valtype(u)?);
2306 Ok(true)
2307 })?;
2308 Ok(ret)
2309 }
2310
2311 fn arbitrary_data(&mut self, u: &mut Unstructured) -> Result<()> {
2312 let memories = self.memories.len() as u32;
2315 if memories == 0 && !self.config.bulk_memory_enabled {
2316 return Ok(());
2317 }
2318 let disallow_traps = self.config.disallow_traps;
2319 let mut choices32: Vec<Box<dyn Fn(&mut Unstructured, u64, usize) -> Result<Offset>>> =
2320 vec![];
2321 choices32.push(Box::new(|u, min_size, data_len| {
2322 let min = u32::try_from(min_size.saturating_mul(64 * 1024))
2323 .unwrap_or(u32::MAX)
2324 .into();
2325 let max = if disallow_traps { min } else { u32::MAX.into() };
2326 Ok(Offset::Const32(
2327 arbitrary_offset(u, min, max, data_len)? as i32
2328 ))
2329 }));
2330 let mut choices64: Vec<Box<dyn Fn(&mut Unstructured, u64, usize) -> Result<Offset>>> =
2331 vec![];
2332 choices64.push(Box::new(|u, min_size, data_len| {
2333 let min = min_size.saturating_mul(64 * 1024);
2334 let max = if disallow_traps { min } else { u64::MAX };
2335 Ok(Offset::Const64(
2336 arbitrary_offset(u, min, max, data_len)? as i64
2337 ))
2338 }));
2339 if !self.config.disallow_traps {
2340 for i in self.globals_for_const_expr(ValType::I32) {
2341 choices32.push(Box::new(move |_, _, _| Ok(Offset::Global(i))));
2342 }
2343 for i in self.globals_for_const_expr(ValType::I64) {
2344 choices64.push(Box::new(move |_, _, _| Ok(Offset::Global(i))));
2345 }
2346 }
2347
2348 let mut memories = Vec::new();
2354 for (i, mem) in self.memories.iter().enumerate() {
2355 if mem.minimum > 0 || u.int_in_range(0..=CHANCE_SEGMENT_ON_EMPTY)? == 0 {
2356 memories.push(i as u32);
2357 }
2358 }
2359
2360 if memories.is_empty() && !self.config.bulk_memory_enabled {
2364 return Ok(());
2365 }
2366
2367 arbitrary_loop(
2368 u,
2369 self.config.min_data_segments,
2370 self.config.max_data_segments,
2371 |u| {
2372 let mut init: Vec<u8> = u.arbitrary()?;
2373
2374 let kind =
2379 if self.config.bulk_memory_enabled && (memories.is_empty() || u.arbitrary()?) {
2380 DataSegmentKind::Passive
2381 } else {
2382 let memory_index = *u.choose(&memories)?;
2383 let mem = &self.memories[memory_index as usize];
2384 let f = if mem.memory64 {
2385 u.choose(&choices64)?
2386 } else {
2387 u.choose(&choices32)?
2388 };
2389 let mut offset = f(u, mem.minimum, init.len())?;
2390
2391 if self.config.disallow_traps {
2396 let max_size = (u64::MAX / 64 / 1024).min(mem.minimum) * 64 * 1024;
2397 init.truncate(max_size as usize);
2398 let max_offset = max_size - init.len() as u64;
2399 match &mut offset {
2400 Offset::Const32(x) => {
2401 *x = (*x as u64).min(max_offset) as i32;
2402 }
2403 Offset::Const64(x) => {
2404 *x = (*x as u64).min(max_offset) as i64;
2405 }
2406 Offset::Global(_) => unreachable!(),
2407 }
2408 }
2409 DataSegmentKind::Active {
2410 offset,
2411 memory_index,
2412 }
2413 };
2414 self.data.push(DataSegment { kind, init });
2415 Ok(true)
2416 },
2417 )
2418 }
2419
2420 fn params_results(&self, ty: &BlockType) -> (Vec<ValType>, Vec<ValType>) {
2421 match ty {
2422 BlockType::Empty => (vec![], vec![]),
2423 BlockType::Result(t) => (vec![], vec![*t]),
2424 BlockType::FunctionType(ty) => {
2425 let ty = self.func_type(*ty);
2426 (ty.params.to_vec(), ty.results.to_vec())
2427 }
2428 }
2429 }
2430
2431 fn globals_for_const_expr(&self, ty: ValType) -> impl Iterator<Item = u32> + '_ {
2434 let num_imported_globals = self.globals.len() - self.defined_globals.len();
2437 let max_global = if self.config.gc_enabled {
2438 self.globals.len()
2439 } else {
2440 num_imported_globals
2441 };
2442
2443 self.globals[..max_global]
2444 .iter()
2445 .enumerate()
2446 .filter_map(move |(i, g)| {
2447 if !g.mutable && self.val_type_is_sub_type(g.val_type, ty) {
2451 Some(i as u32)
2452 } else {
2453 None
2454 }
2455 })
2456 }
2457
2458 fn compute_interesting_values(&mut self) {
2459 debug_assert!(self.interesting_values32.is_empty());
2460 debug_assert!(self.interesting_values64.is_empty());
2461
2462 let mut interesting_values32 = HashSet::new();
2463 let mut interesting_values64 = HashSet::new();
2464
2465 let mut interesting = |val: u64| {
2466 interesting_values32.insert(val as u32);
2467 interesting_values64.insert(val);
2468 };
2469
2470 interesting(0);
2472
2473 interesting(u8::MAX as _);
2475 interesting(u16::MAX as _);
2476 interesting(u32::MAX as _);
2477 interesting(u64::MAX);
2478
2479 interesting(i8::MIN as _);
2481 interesting(i16::MIN as _);
2482 interesting(i32::MIN as _);
2483 interesting(i64::MIN as _);
2484
2485 for i in 0..64 {
2486 interesting(1 << i);
2488
2489 interesting(!(1 << i));
2491
2492 interesting((1 << i) - 1);
2494
2495 interesting(((1_i64 << 63) >> i) as _);
2497 }
2498
2499 for pattern in [0b01010101, 0b00010001, 0b00010001, 0b00000001] {
2501 for b in [pattern, !pattern] {
2502 interesting(u64::from_ne_bytes([b, b, b, b, b, b, b, b]));
2503 }
2504 }
2505
2506 let mut interesting_f64 = |x: f64| interesting(x.to_bits());
2508 interesting_f64(0.0);
2509 interesting_f64(-0.0);
2510 interesting_f64(f64::INFINITY);
2511 interesting_f64(f64::NEG_INFINITY);
2512 interesting_f64(f64::EPSILON);
2513 interesting_f64(-f64::EPSILON);
2514 interesting_f64(f64::MIN);
2515 interesting_f64(f64::MIN_POSITIVE);
2516 interesting_f64(f64::MAX);
2517 interesting_f64(f64::NAN);
2518 let mut interesting_f32 = |x: f32| interesting(x.to_bits() as _);
2519 interesting_f32(0.0);
2520 interesting_f32(-0.0);
2521 interesting_f32(f32::INFINITY);
2522 interesting_f32(f32::NEG_INFINITY);
2523 interesting_f32(f32::EPSILON);
2524 interesting_f32(-f32::EPSILON);
2525 interesting_f32(f32::MIN);
2526 interesting_f32(f32::MIN_POSITIVE);
2527 interesting_f32(f32::MAX);
2528 interesting_f32(f32::NAN);
2529
2530 for t in self.tables.iter() {
2532 interesting(t.minimum as _);
2533 if let Some(x) = t.minimum.checked_add(1) {
2534 interesting(x as _);
2535 }
2536
2537 if let Some(x) = t.maximum {
2538 interesting(x as _);
2539 if let Some(y) = x.checked_add(1) {
2540 interesting(y as _);
2541 }
2542 }
2543 }
2544
2545 for m in self.memories.iter() {
2547 let min = m.minimum.saturating_mul(crate::page_size(m).into());
2548 interesting(min);
2549 for i in 0..5 {
2550 if let Some(x) = min.checked_add(1 << i) {
2551 interesting(x);
2552 }
2553 if let Some(x) = min.checked_sub(1 << i) {
2554 interesting(x);
2555 }
2556 }
2557
2558 if let Some(max) = m.maximum {
2559 let max = max.saturating_mul(crate::page_size(m).into());
2560 interesting(max);
2561 for i in 0..5 {
2562 if let Some(x) = max.checked_add(1 << i) {
2563 interesting(x);
2564 }
2565 if let Some(x) = max.checked_sub(1 << i) {
2566 interesting(x);
2567 }
2568 }
2569 }
2570 }
2571
2572 self.interesting_values32.extend(interesting_values32);
2573 self.interesting_values64.extend(interesting_values64);
2574
2575 self.interesting_values32.sort();
2577 self.interesting_values64.sort();
2578 }
2579
2580 fn arbitrary_const_instruction(
2581 &self,
2582 ty: ValType,
2583 u: &mut Unstructured<'_>,
2584 ) -> Result<Instruction> {
2585 debug_assert!(self.interesting_values32.len() > 0);
2586 debug_assert!(self.interesting_values64.len() > 0);
2587 match ty {
2588 ValType::I32 => Ok(Instruction::I32Const(if u.arbitrary()? {
2589 *u.choose(&self.interesting_values32)? as i32
2590 } else {
2591 u.arbitrary()?
2592 })),
2593 ValType::I64 => Ok(Instruction::I64Const(if u.arbitrary()? {
2594 *u.choose(&self.interesting_values64)? as i64
2595 } else {
2596 u.arbitrary()?
2597 })),
2598 ValType::F32 => Ok(Instruction::F32Const(if u.arbitrary()? {
2599 f32::from_bits(*u.choose(&self.interesting_values32)?)
2600 } else {
2601 u.arbitrary()?
2602 })),
2603 ValType::F64 => Ok(Instruction::F64Const(if u.arbitrary()? {
2604 f64::from_bits(*u.choose(&self.interesting_values64)?)
2605 } else {
2606 u.arbitrary()?
2607 })),
2608 ValType::V128 => Ok(Instruction::V128Const(if u.arbitrary()? {
2609 let upper = (*u.choose(&self.interesting_values64)? as i128) << 64;
2610 let lower = *u.choose(&self.interesting_values64)? as i128;
2611 upper | lower
2612 } else {
2613 u.arbitrary()?
2614 })),
2615 ValType::Ref(ty) => {
2616 assert!(ty.nullable);
2617 Ok(Instruction::RefNull(ty.heap_type))
2618 }
2619 }
2620 }
2621
2622 fn propagate_shared<T>(&mut self, must_share: bool, mut f: impl FnMut(&mut Self) -> T) -> T {
2623 let tmp = mem::replace(&mut self.must_share, must_share);
2624 let result = f(self);
2625 self.must_share = tmp;
2626 result
2627 }
2628
2629 fn arbitrary_shared(&self, u: &mut Unstructured) -> Result<bool> {
2630 if self.must_share {
2631 Ok(true)
2632 } else {
2633 Ok(self.config.shared_everything_threads_enabled && u.ratio(1, 4)?)
2634 }
2635 }
2636
2637 fn is_shared_ref_type(&self, ty: RefType) -> bool {
2638 match ty.heap_type {
2639 HeapType::Abstract { shared, .. } => shared,
2640 HeapType::Concrete(i) => self.types[i as usize].composite_type.shared,
2641 }
2642 }
2643
2644 fn is_shared_type(&self, index: u32) -> bool {
2645 let index = usize::try_from(index).unwrap();
2646 let ty = self.types.get(index).unwrap();
2647 ty.composite_type.shared
2648 }
2649}
2650
2651pub(crate) fn arbitrary_limits64(
2652 u: &mut Unstructured,
2653 min_minimum: Option<u64>,
2654 max_minimum: u64,
2655 max_required: bool,
2656 max_inbounds: u64,
2657) -> Result<(u64, Option<u64>)> {
2658 assert!(
2659 min_minimum.unwrap_or(0) <= max_minimum,
2660 "{} <= {max_minimum}",
2661 min_minimum.unwrap_or(0),
2662 );
2663 assert!(
2664 min_minimum.unwrap_or(0) <= max_inbounds,
2665 "{} <= {max_inbounds}",
2666 min_minimum.unwrap_or(0),
2667 );
2668
2669 let min = gradually_grow(u, min_minimum.unwrap_or(0), max_inbounds, max_minimum)?;
2670 assert!(min <= max_minimum, "{min} <= {max_minimum}");
2671
2672 let max = if max_required || u.arbitrary().unwrap_or(false) {
2673 Some(u.int_in_range(min..=max_minimum)?)
2674 } else {
2675 None
2676 };
2677 assert!(min <= max.unwrap_or(min), "{min} <= {}", max.unwrap_or(min));
2678
2679 Ok((min, max))
2680}
2681
2682pub(crate) fn configured_valtypes(config: &Config) -> Vec<ValType> {
2683 let mut valtypes = Vec::with_capacity(25);
2684 valtypes.push(ValType::I32);
2685 valtypes.push(ValType::I64);
2686 if config.allow_floats {
2687 valtypes.push(ValType::F32);
2688 valtypes.push(ValType::F64);
2689 }
2690 if config.simd_enabled {
2691 valtypes.push(ValType::V128);
2692 }
2693 if config.gc_enabled && config.reference_types_enabled {
2694 for nullable in [
2695 true,
2702 ] {
2703 use AbstractHeapType::*;
2704 let abs_ref_types = [
2705 Any, Eq, I31, Array, Struct, None, Func, NoFunc, Extern, NoExtern,
2706 ];
2707 valtypes.extend(
2708 abs_ref_types
2709 .iter()
2710 .map(|&ty| ValType::Ref(RefType::new_abstract(ty, nullable, false))),
2711 );
2712 if config.shared_everything_threads_enabled {
2713 valtypes.extend(
2714 abs_ref_types
2715 .iter()
2716 .map(|&ty| ValType::Ref(RefType::new_abstract(ty, nullable, true))),
2717 );
2718 }
2719 }
2720 } else if config.reference_types_enabled {
2721 valtypes.push(ValType::EXTERNREF);
2722 valtypes.push(ValType::FUNCREF);
2723 }
2724 valtypes
2725}
2726
2727pub(crate) fn arbitrary_table_type(
2728 u: &mut Unstructured,
2729 config: &Config,
2730 module: Option<&Module>,
2731) -> Result<TableType> {
2732 let table64 = config.memory64_enabled && u.arbitrary()?;
2733 let max_inbounds = 10_000;
2736 let min_elements = if config.disallow_traps { Some(1) } else { None };
2737 let max_elements = min_elements.unwrap_or(0).max(config.max_table_elements);
2738 let (minimum, maximum) = arbitrary_limits64(
2739 u,
2740 min_elements,
2741 max_elements,
2742 config.table_max_size_required,
2743 max_inbounds.min(max_elements),
2744 )?;
2745 if config.disallow_traps {
2746 assert!(minimum > 0);
2747 }
2748 let element_type = match module {
2749 Some(module) => module.arbitrary_ref_type(u)?,
2750 None => RefType::FUNCREF,
2751 };
2752
2753 let shared = match module {
2755 Some(module) => module.is_shared_ref_type(element_type),
2756 None => false,
2757 };
2758
2759 Ok(TableType {
2760 element_type,
2761 minimum,
2762 maximum,
2763 table64,
2764 shared,
2765 })
2766}
2767
2768pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result<MemoryType> {
2769 let shared = config.threads_enabled && u.ratio(1, 4)?;
2772
2773 let memory64 = config.memory64_enabled && u.arbitrary()?;
2774 let page_size_log2 = if config.custom_page_sizes_enabled && u.arbitrary()? {
2775 Some(if u.arbitrary()? { 0 } else { 16 })
2776 } else {
2777 None
2778 };
2779
2780 let min_pages = if config.disallow_traps { Some(1) } else { None };
2781 let max_pages = min_pages.unwrap_or(0).max(if memory64 {
2782 u64::try_from(config.max_memory64_bytes >> page_size_log2.unwrap_or(16))
2783 .unwrap_or(u64::MAX as u64)
2787 } else {
2788 u32::try_from(config.max_memory32_bytes >> page_size_log2.unwrap_or(16))
2789 .unwrap_or(u32::MAX)
2792 .into()
2793 });
2794
2795 let max_all_mems_in_bytes = 1 << 30;
2797 let max_this_mem_in_bytes = max_all_mems_in_bytes / u64::try_from(config.max_memories).unwrap();
2798 let max_inbounds = max_this_mem_in_bytes >> page_size_log2.unwrap_or(16);
2799 let max_inbounds = max_inbounds.clamp(min_pages.unwrap_or(0), max_pages);
2800
2801 let (minimum, maximum) = arbitrary_limits64(
2802 u,
2803 min_pages,
2804 max_pages,
2805 config.memory_max_size_required || shared,
2806 max_inbounds,
2807 )?;
2808
2809 Ok(MemoryType {
2810 minimum,
2811 maximum,
2812 memory64,
2813 shared,
2814 page_size_log2,
2815 })
2816}
2817
2818pub(crate) fn arbitrary_tag_type(
2819 u: &mut Unstructured,
2820 candidate_func_types: &[u32],
2821 get_func_type: impl FnOnce(u32) -> Rc<FuncType>,
2822) -> Result<TagType> {
2823 let max = candidate_func_types.len() - 1;
2824 let ty = candidate_func_types[u.int_in_range(0..=max)?];
2825 Ok(TagType {
2826 func_type_idx: ty,
2827 func_type: get_func_type(ty),
2828 })
2829}
2830
2831fn gradually_grow(u: &mut Unstructured, min: u64, max_inbounds: u64, max: u64) -> Result<u64> {
2839 if min == max {
2840 return Ok(min);
2841 }
2842 let x = {
2843 let min = min as f64;
2844 let max = max as f64;
2845 let max_inbounds = max_inbounds as f64;
2846 let x = u.arbitrary::<u32>()?;
2847 let x = f64::from(x);
2848 let x = map_custom(
2849 x,
2850 f64::from(u32::MIN)..f64::from(u32::MAX),
2851 min..max_inbounds,
2852 min..max,
2853 );
2854 assert!(min <= x, "{min} <= {x}");
2855 assert!(x <= max, "{x} <= {max}");
2856 x.round() as u64
2857 };
2858
2859 return Ok(x.clamp(min, max));
2862
2863 fn map_custom(
2870 value: f64,
2871 input: Range<f64>,
2872 output_inbounds: Range<f64>,
2873 output: Range<f64>,
2874 ) -> f64 {
2875 assert!(!value.is_nan(), "{}", value);
2876 assert!(value.is_finite(), "{}", value);
2877 assert!(input.start < input.end, "{} < {}", input.start, input.end);
2878 assert!(
2879 output.start < output.end,
2880 "{} < {}",
2881 output.start,
2882 output.end
2883 );
2884 assert!(value >= input.start, "{} >= {}", value, input.start);
2885 assert!(value <= input.end, "{} <= {}", value, input.end);
2886 assert!(
2887 output.start <= output_inbounds.start,
2888 "{} <= {}",
2889 output.start,
2890 output_inbounds.start
2891 );
2892 assert!(
2893 output_inbounds.end <= output.end,
2894 "{} <= {}",
2895 output_inbounds.end,
2896 output.end
2897 );
2898
2899 let x = map_linear(value, input, 0.0..1.0);
2900 let result = if x < PCT_INBOUNDS {
2901 if output_inbounds.start == output_inbounds.end {
2902 output_inbounds.start
2903 } else {
2904 let unscaled = x * x * x * x * x * x;
2905 map_linear(unscaled, 0.0..1.0, output_inbounds)
2906 }
2907 } else {
2908 map_linear(x, 0.0..1.0, output.clone())
2909 };
2910
2911 assert!(result >= output.start, "{} >= {}", result, output.start);
2912 assert!(result <= output.end, "{} <= {}", result, output.end);
2913 result
2914 }
2915
2916 fn map_linear(
2921 value: f64,
2922 Range {
2923 start: in_low,
2924 end: in_high,
2925 }: Range<f64>,
2926 Range {
2927 start: out_low,
2928 end: out_high,
2929 }: Range<f64>,
2930 ) -> f64 {
2931 assert!(!value.is_nan(), "{}", value);
2932 assert!(value.is_finite(), "{}", value);
2933 assert!(in_low < in_high, "{} < {}", in_low, in_high);
2934 assert!(out_low < out_high, "{} < {}", out_low, out_high);
2935 assert!(value >= in_low, "{} >= {}", value, in_low);
2936 assert!(value <= in_high, "{} <= {}", value, in_high);
2937
2938 let dividend = out_high - out_low;
2939 let divisor = in_high - in_low;
2940 let slope = dividend / divisor;
2941 let result = out_low + (slope * (value - in_low));
2942
2943 assert!(result >= out_low, "{} >= {}", result, out_low);
2944 assert!(result <= out_high, "{} <= {}", result, out_high);
2945 result
2946 }
2947}
2948
2949fn arbitrary_offset(
2953 u: &mut Unstructured,
2954 limit_min: u64,
2955 limit_max: u64,
2956 segment_size: usize,
2957) -> Result<u64> {
2958 let size = u64::try_from(segment_size).unwrap();
2959
2960 if size > limit_min {
2963 u.int_in_range(0..=limit_max)
2964 } else {
2965 gradually_grow(u, 0, limit_min - size, limit_max)
2966 }
2967}
2968
2969fn unique_import_strings(max_size: usize, u: &mut Unstructured) -> Result<(String, String)> {
2970 let module = limited_string(max_size, u)?;
2971 let field = limited_string(max_size, u)?;
2972 Ok((module, field))
2973}
2974
2975fn arbitrary_vec_u8(u: &mut Unstructured) -> Result<Vec<u8>> {
2976 let size = u.arbitrary_len::<u8>()?;
2977 Ok(u.bytes(size)?.to_vec())
2978}
2979
2980impl EntityType {
2981 fn size(&self) -> u32 {
2982 match self {
2983 EntityType::Tag(_)
2984 | EntityType::Global(_)
2985 | EntityType::Table(_)
2986 | EntityType::Memory(_) => 1,
2987 EntityType::Func(_, ty) => 1 + (ty.params.len() + ty.results.len()) as u32,
2988 }
2989 }
2990}
2991
2992#[derive(Clone, Copy, Debug, Default)]
3003#[cfg_attr(feature = "serde_derive", derive(serde_derive::Deserialize))]
3004pub struct InstructionKinds(pub(crate) FlagSet<InstructionKind>);
3005
3006impl InstructionKinds {
3007 pub fn new(kinds: &[InstructionKind]) -> Self {
3009 Self(kinds.iter().fold(FlagSet::default(), |ks, k| ks | *k))
3010 }
3011
3012 pub fn all() -> Self {
3014 Self(FlagSet::full())
3015 }
3016
3017 pub fn none() -> Self {
3019 Self(FlagSet::default())
3020 }
3021
3022 #[inline]
3024 pub fn contains(&self, kind: InstructionKind) -> bool {
3025 self.0.contains(kind)
3026 }
3027
3028 pub fn without_floats(&self) -> Self {
3030 let mut floatless = self.0;
3031 if floatless.contains(InstructionKind::Numeric) {
3032 floatless -= InstructionKind::Numeric;
3033 floatless |= InstructionKind::NumericInt;
3034 }
3035 if floatless.contains(InstructionKind::Vector) {
3036 floatless -= InstructionKind::Vector;
3037 floatless |= InstructionKind::VectorInt;
3038 }
3039 if floatless.contains(InstructionKind::Memory) {
3040 floatless -= InstructionKind::Memory;
3041 floatless |= InstructionKind::MemoryInt;
3042 }
3043 Self(floatless)
3044 }
3045}
3046
3047flags! {
3048 #[allow(missing_docs)]
3051 #[cfg_attr(feature = "_internal_cli", derive(serde_derive::Deserialize))]
3052 pub enum InstructionKind: u16 {
3053 NumericInt = 1 << 0,
3054 Numeric = (1 << 1) | (1 << 0),
3055 VectorInt = 1 << 2,
3056 Vector = (1 << 3) | (1 << 2),
3057 Reference = 1 << 4,
3058 Parametric = 1 << 5,
3059 Variable = 1 << 6,
3060 Table = 1 << 7,
3061 MemoryInt = 1 << 8,
3062 Memory = (1 << 9) | (1 << 8),
3063 Control = 1 << 10,
3064 Aggregate = 1 << 11,
3065 }
3066}
3067
3068impl FromStr for InstructionKinds {
3069 type Err = String;
3070 fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
3071 let mut kinds = vec![];
3072 for part in s.split(",") {
3073 let kind = InstructionKind::from_str(part)?;
3074 kinds.push(kind);
3075 }
3076 Ok(InstructionKinds::new(&kinds))
3077 }
3078}
3079
3080impl FromStr for InstructionKind {
3081 type Err = String;
3082 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
3083 match s.to_lowercase().as_str() {
3084 "numeric_non_float" => Ok(InstructionKind::NumericInt),
3085 "numeric" => Ok(InstructionKind::Numeric),
3086 "vector_non_float" => Ok(InstructionKind::VectorInt),
3087 "vector" => Ok(InstructionKind::Vector),
3088 "reference" => Ok(InstructionKind::Reference),
3089 "parametric" => Ok(InstructionKind::Parametric),
3090 "variable" => Ok(InstructionKind::Variable),
3091 "table" => Ok(InstructionKind::Table),
3092 "memory_non_float" => Ok(InstructionKind::MemoryInt),
3093 "memory" => Ok(InstructionKind::Memory),
3094 "control" => Ok(InstructionKind::Control),
3095 _ => Err(format!("unknown instruction kind: {}", s)),
3096 }
3097 }
3098}