Skip to main content

wasmtime_fuzzing/generators/gc_ops/
limits.rs

1//! Limits for the `gc` operations.
2
3use serde::{Deserialize, Serialize};
4use std::ops::RangeInclusive;
5
6/// Range for the number of parameters.
7pub const NUM_PARAMS_RANGE: RangeInclusive<u32> = 0..=10;
8/// Range for the maximum number of types.
9pub const MAX_TYPES_RANGE: RangeInclusive<u32> = 0..=32;
10/// Range for the number of globals.
11pub const NUM_GLOBALS_RANGE: RangeInclusive<u32> = 0..=10;
12/// Range for the table size.
13pub const TABLE_SIZE_RANGE: RangeInclusive<u32> = 0..=100;
14/// Range for the maximum number of rec groups.
15pub const MAX_REC_GROUPS_RANGE: RangeInclusive<u32> = 0..=10;
16/// Range for the maximum number of fields per struct type.
17pub const MAX_FIELDS_RANGE: RangeInclusive<u32> = 0..=8;
18/// Range for the length of created arrays.
19pub const ARRAY_LENGTH_RANGE: RangeInclusive<u32> = 1..=16;
20/// Maximum number of fields that can be inlined in a struct type.
21pub const MAX_INLINE_CONSTRUCTION: u32 = 8;
22
23/// Limits controlling the structure of a generated Wasm module.
24#[derive(Clone, Debug, Serialize, Deserialize, mutatis::Mutate)]
25pub struct GcOpsLimits {
26    /// Number of `externref` parameters of `run`.
27    #[mutatis(default_mutate)]
28    pub(crate) num_params: u32,
29    /// Number of `externref` globals.
30    #[mutatis(default_mutate)]
31    pub(crate) num_globals: u32,
32    /// Number of elements in every table.
33    #[mutatis(default_mutate)]
34    pub(crate) table_size: u32,
35    /// Maximum number of rec groups.
36    #[mutatis(default_mutate)]
37    pub(crate) max_rec_groups: u32,
38    /// Maximum number of concrete types.
39    #[mutatis(default_mutate)]
40    pub(crate) max_types: u32,
41    /// Maximum number of fields per struct type.
42    #[mutatis(default_mutate)]
43    pub(crate) max_fields: u32,
44    /// Length of every array created by `ArrayNew` and `ArrayNewDefault`.
45    #[mutatis(default_mutate)]
46    pub(crate) array_length: u32,
47}
48
49impl Default for GcOpsLimits {
50    fn default() -> Self {
51        Self {
52            num_params: 5,
53            num_globals: 5,
54            table_size: 5,
55            max_rec_groups: 5,
56            max_types: 5,
57            max_fields: 5,
58            array_length: 5,
59        }
60    }
61}
62
63impl GcOpsLimits {
64    /// Fixup the limits to ensure they are within the valid range.
65    pub(crate) fn fixup_limits(&mut self) {
66        let Self {
67            num_params,
68            num_globals,
69            table_size,
70            max_rec_groups,
71            max_types,
72            max_fields,
73            array_length,
74        } = self;
75
76        let fixup = |limit: &mut u32, range: RangeInclusive<u32>| {
77            if !range.contains(limit) {
78                let (start, end) = (*range.start(), *range.end());
79                *limit = start + *limit % (end - start + 1);
80            }
81        };
82        fixup(table_size, TABLE_SIZE_RANGE);
83        fixup(num_params, NUM_PARAMS_RANGE);
84        fixup(num_globals, NUM_GLOBALS_RANGE);
85        fixup(max_rec_groups, MAX_REC_GROUPS_RANGE);
86        fixup(max_types, MAX_TYPES_RANGE);
87        fixup(max_fields, MAX_FIELDS_RANGE);
88        fixup(array_length, ARRAY_LENGTH_RANGE);
89    }
90}