1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
pub
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
/// A default stack size we use for stack allocation.
///
/// This value can't be less than 6, because 4 elements we need for an entrypoint and 1 element
/// we need for running e2e testing suite where one parameter can be passed into the test.
///
/// We keep value 32 since it's the most optimal.
pub const N_DEFAULT_STACK_SIZE: usize = 32;
pub const N_MAX_STACK_SIZE: usize = 8192;
pub const N_MAX_RECURSION_DEPTH: usize = 1024;
/// This constant is driven by WebAssembly standard, default
/// memory page size is 64kB
pub const N_BYTES_PER_MEMORY_PAGE: u32 = 65536;
/// A default number of memory pages 1024 pages (64mB)
pub const N_DEFAULT_MAX_MEMORY_PAGES: u32 = 1024;
/// A hard limit on the maximum number of memory pages that can be allocated.
/// This value is driven from a Wasm standard, the maximum number of memory pages is 32,768.
///
/// # Safety
///
/// The compiler-injected prologues for `memory.grow`/`memory.init` (see [`crate::InstructionSet`]
/// in `src/isa/memory.rs`) compare `size + delta` against this limit with a *signed* `i32.gt_s`
/// and compute fuel with a *wrapping* `i32.add` round-up. Both can be defeated by an operand
/// close to `i32::MAX`/`u32::MAX`: the sum wraps negative and passes the guard, and the fuel
/// round-up wraps down to (nearly) zero fuel.
///
/// This is currently not exploitable only because such inputs always trap on the runtime bounds
/// check that runs behind the guard: `32768 * 65536` fits in `u32`, so no reachable page count
/// can make the wrapped path touch memory or skip metering for work actually performed.
/// Raising this constant, or otherwise letting the guards see values that overflow `i32`, would
/// turn those prologues into a real bounds/metering bypass with no visible change to this code.
/// Change it only together with switching the guards to unsigned comparisons and overflow-safe
/// fuel arithmetic.
pub const N_MAX_ALLOWED_MEMORY_PAGES: u32 = 32768;
/// A default memory index in a Wasm binary.
/// According to Wasm validation rules, this value is always 0,
/// since Wasm doesn't support multiple memory segments yet
pub const DEFAULT_MEMORY_INDEX: u32 = 0;
pub const N_MAX_DATA_SEGMENTS: usize = 100_000;
pub const N_MAX_ELEM_SEGMENTS: usize = 100_000;
pub const N_MAX_DATA_SEGMENTS_BITS: usize =
N_MAX_DATA_SEGMENTS.div_ceil;
pub const N_MAX_ELEM_SEGMENTS_BITS: usize =
N_MAX_ELEM_SEGMENTS.div_ceil;
/// For null RefFunc/ExternRef types we use 0. We can do this
/// because 0 offset is reserved under an entrypoint that can't be re-called
pub const NULL_FUNC_IDX: u32 = 0u32;
/// Placeholder for the function index of a snippet.
/// The actual index is resolved in later compilation stages
/// once the snippet's final location is known.
pub const SNIPPET_FUNC_IDX_UNRESOLVED: u32 = u32MAX;
/// That maximum possible number of tables allowed, the limited is driven from Wasm standards
pub const N_MAX_TABLES: u32 = 100;
/// The maximum limit of elements in total can be fit into one table.
/// It means in total you can have `100*1024=102_400` elements.
///
/// The original standard allows `100_000` element segments with an unlimited number of elements
/// inside.
///
/// # Safety
///
/// The same caveat as for [`N_MAX_ALLOWED_MEMORY_PAGES`] applies: the injected prologues for
/// `table.grow`/`table.init` (`src/isa/table.rs`) use signed `i32.gt_s` on `size + delta` and a
/// wrapping `i32.add` for the fuel round-up. With this limit the guarded sums stay far below
/// `i32::MAX`, so the signedness and the wrap are unobservable, and any input large enough to
/// wrap traps on the runtime table bounds check anyway. Raising this constant to anything near
/// `i32::MAX` requires switching those guards to unsigned comparisons and overflow-safe fuel
/// arithmetic first.
pub const N_MAX_TABLE_SIZE: u32 = 1024;
pub type InstrLoc = u32;
pub type LabelRef = u32;
pub type FuncTypeIdx = u32;
pub type SignatureIdx = u32;
pub type MemoryIdx = u32;
pub type GlobalIdx = u32;
/// Max table size can't exceed 100 elements, so it easily fits into u16
pub type TableIdx = u16;
pub type FuncIdx = u32;
pub type DataSegmentIdx = u32;
pub type ElementSegmentIdx = u32;
pub type CompiledFunc = u32;
pub type LocalDepth = u32;
pub type BranchTableTargets = u32;
pub type MaxStackHeight = u32;
pub type SysFuncIdx = u32;
pub type AddressOffset = u32;
pub type BlockFuel = u32;
pub type NumLocals = u32;