wasm/validation/modules/
data_segments.rs

1use crate::{
2    core::{
3        decoding::reader::WasmDecoder,
4        structure::{
5            modules::{
6                data_segments::{DataMode, DataModeActive, DataSegment},
7                indices::{FuncIdx, IdxVec, MemIdx, TypeIdx},
8            },
9            types::GlobalType,
10        },
11    },
12    validation::{
13        instructions::constant_expressions::decode_and_validate_constant_expression,
14        validation_stack::ValidationStack,
15    },
16    MemType, ValidationError,
17};
18
19impl DataSegment {
20    pub fn decode_and_validate(
21        wasm: &mut WasmDecoder,
22        imported_global_types: &[GlobalType],
23        c_funcs: &IdxVec<FuncIdx, TypeIdx>,
24        c_mems: &IdxVec<MemIdx, MemType>,
25    ) -> Result<Self, ValidationError> {
26        use crate::{NumType, ValType};
27        let mode = wasm.decode_var_u32()?;
28        let data_sec: DataSegment = match mode {
29            0 => {
30                // active { memory 0, offset e }
31                trace!("Data section: active {{ memory 0, offset e }}");
32
33                let _mem_idx = MemIdx::validate(0, c_mems)?;
34
35                let mut valid_stack = ValidationStack::new();
36                let (offset, _) = {
37                    decode_and_validate_constant_expression(
38                        wasm,
39                        &mut valid_stack,
40                        imported_global_types,
41                        c_funcs,
42                    )?
43                };
44
45                valid_stack.assert_val_types(&[ValType::NumType(NumType::I32)], true)?;
46
47                let byte_vec = wasm.decode_vec(|el| el.decode_u8())?;
48
49                // WARN: we currently don't take into consideration how we act when we are dealing with globals here
50                DataSegment {
51                    mode: DataMode::Active(DataModeActive {
52                        memory_idx: MemIdx::validate(0, c_mems)?,
53                        offset,
54                    }),
55                    init: byte_vec,
56                }
57            }
58            1 => {
59                // passive
60                // A passive data segment's contents can be copied into a memory using the `memory.init` instruction
61                trace!("Data section: passive");
62                DataSegment {
63                    mode: DataMode::Passive,
64                    init: wasm.decode_vec(|el| el.decode_u8())?,
65                }
66            }
67            2 => {
68                trace!("Data section: active {{ memory x, offset e }}");
69                let mem_idx = MemIdx::decode_and_validate(wasm, c_mems)?;
70
71                let mut valid_stack = ValidationStack::new();
72                let (offset, _) = {
73                    decode_and_validate_constant_expression(
74                        wasm,
75                        &mut valid_stack,
76                        imported_global_types,
77                        c_funcs,
78                    )?
79                };
80
81                valid_stack.assert_val_types(&[ValType::NumType(NumType::I32)], true)?;
82
83                let byte_vec = wasm.decode_vec(|el| el.decode_u8())?;
84
85                DataSegment {
86                    mode: DataMode::Active(DataModeActive {
87                        memory_idx: mem_idx,
88                        offset,
89                    }),
90                    init: byte_vec,
91                }
92                // mode active { memory x, offset e }
93                // this hasn't been yet implemented in wasm
94                // as per docs:
95
96                // https://webassembly.github.io/spec/core/binary/modules.html#data-section
97                // The initial integer can be interpreted as a bitfield. Bit 0 indicates a passive segment, bit 1 indicates the presence of an explicit memory index for an active segment.
98                // In the current version of WebAssembly, at most one memory may be defined or imported in a single module, so all valid active data segments have a memory value of 0
99            }
100            invalid_mode @ 3.. => {
101                return Err(ValidationError::InvalidDataSegmentMode(invalid_mode))
102            }
103        };
104
105        trace!("{:?}", data_sec.init);
106        Ok(data_sec)
107    }
108}