wasm/validation/
data.rs

1use alloc::vec::Vec;
2
3use crate::{
4    core::{
5        indices::{FuncIdx, IdxVec, MemIdx, TypeIdx},
6        reader::{
7            section_header::{SectionHeader, SectionTy},
8            types::{
9                data::{DataMode, DataModeActive, DataSegment},
10                global::GlobalType,
11            },
12            WasmReader,
13        },
14    },
15    read_constant_expression::read_constant_expression,
16    validation_stack::ValidationStack,
17    MemType, ValidationError,
18};
19
20/// Validate the data section.
21pub(super) fn validate_data_section(
22    wasm: &mut WasmReader,
23    section_header: SectionHeader,
24    imported_global_types: &[GlobalType],
25    c_funcs: &IdxVec<FuncIdx, TypeIdx>,
26    c_mems: &IdxVec<MemIdx, MemType>,
27) -> Result<Vec<DataSegment>, ValidationError> {
28    assert_eq!(section_header.ty, SectionTy::Data);
29
30    wasm.read_vec(|wasm| {
31        use crate::{NumType, ValType};
32        let mode = wasm.read_var_u32()?;
33        let data_sec: DataSegment = match mode {
34            0 => {
35                // active { memory 0, offset e }
36                trace!("Data section: active {{ memory 0, offset e }}");
37
38                let _mem_idx = MemIdx::validate(0, c_mems)?;
39
40                let mut valid_stack = ValidationStack::new();
41                let (offset, _) = {
42                    read_constant_expression(
43                        wasm,
44                        &mut valid_stack,
45                        imported_global_types,
46                        c_funcs,
47                    )?
48                };
49
50                valid_stack.assert_val_types(&[ValType::NumType(NumType::I32)], true)?;
51
52                let byte_vec = wasm.read_vec(|el| el.read_u8())?;
53
54                // WARN: we currently don't take into consideration how we act when we are dealing with globals here
55                DataSegment {
56                    mode: DataMode::Active(DataModeActive {
57                        memory_idx: MemIdx::validate(0, c_mems)?,
58                        offset,
59                    }),
60                    init: byte_vec,
61                }
62            }
63            1 => {
64                // passive
65                // A passive data segment's contents can be copied into a memory using the `memory.init` instruction
66                trace!("Data section: passive");
67                DataSegment {
68                    mode: DataMode::Passive,
69                    init: wasm.read_vec(|el| el.read_u8())?,
70                }
71            }
72            2 => {
73                trace!("Data section: active {{ memory x, offset e }}");
74                let mem_idx = MemIdx::read_and_validate(wasm, c_mems)?;
75
76                let mut valid_stack = ValidationStack::new();
77                let (offset, _) = {
78                    read_constant_expression(
79                        wasm,
80                        &mut valid_stack,
81                        imported_global_types,
82                        c_funcs,
83                    )?
84                };
85
86                valid_stack.assert_val_types(&[ValType::NumType(NumType::I32)], true)?;
87
88                let byte_vec = wasm.read_vec(|el| el.read_u8())?;
89
90                DataSegment {
91                    mode: DataMode::Active(DataModeActive {
92                        memory_idx: mem_idx,
93                        offset,
94                    }),
95                    init: byte_vec,
96                }
97                // mode active { memory x, offset e }
98                // this hasn't been yet implemented in wasm
99                // as per docs:
100
101                // https://webassembly.github.io/spec/core/binary/modules.html#data-section
102                // 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.
103                // 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
104            }
105            invalid_mode @ 3.. => {
106                return Err(ValidationError::InvalidDataSegmentMode(invalid_mode))
107            }
108        };
109
110        trace!("{:?}", data_sec.init);
111        Ok(data_sec)
112    })
113}