wasmparser/readers/core/data.rs
1/* Copyright 2018 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16use crate::{BinaryReader, BinaryReaderError, ConstExpr, FromReader, Result, SectionLimited};
17use core::ops::Range;
18
19/// Represents a data segment in a core WebAssembly module.
20#[derive(Debug, Clone)]
21pub struct Data<'a> {
22 /// The kind of data segment.
23 pub kind: DataKind<'a>,
24 /// The data of the data segment.
25 pub data: &'a [u8],
26 /// The range of the data segment.
27 pub range: Range<usize>,
28}
29
30/// The kind of data segment.
31#[derive(Debug, Clone)]
32pub enum DataKind<'a> {
33 /// The data segment is passive.
34 Passive,
35 /// The data segment is active.
36 Active {
37 /// The memory index for the data segment.
38 memory_index: u32,
39 /// The initialization expression for the data segment.
40 offset_expr: ConstExpr<'a>,
41 },
42}
43
44/// A reader for the data section of a WebAssembly module.
45pub type DataSectionReader<'a> = SectionLimited<'a, Data<'a>>;
46
47impl<'a> FromReader<'a> for Data<'a> {
48 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
49 let segment_start = reader.original_position();
50
51 // The current handling of the flags is largely specified in the `bulk-memory` proposal,
52 // which at the time this comment is written has been merged to the main specification
53 // draft.
54 //
55 // Notably, this proposal allows multiple different encodings of the memory index 0. `00`
56 // and `02 00` are both valid ways to specify the 0-th memory. However it also makes
57 // another encoding of the 0-th memory `80 00` no longer valid.
58 //
59 // We, however maintain this by parsing `flags` as a LEB128 integer. In that case, `80 00`
60 // encoding is parsed out as `0` and is therefore assigned a `memidx` 0, even though the
61 // current specification draft does not allow for this.
62 //
63 // See also https://github.com/WebAssembly/spec/issues/1439
64 let flags = reader.read_var_u32()?;
65 let kind = match flags {
66 1 => DataKind::Passive,
67 0 | 2 => {
68 let memory_index = if flags == 0 {
69 0
70 } else {
71 reader.read_var_u32()?
72 };
73 let offset_expr = reader.read()?;
74 DataKind::Active {
75 memory_index,
76 offset_expr,
77 }
78 }
79 _ => {
80 return Err(BinaryReaderError::new(
81 "invalid flags byte in data segment",
82 segment_start,
83 ));
84 }
85 };
86
87 let data = reader.read_reader()?;
88 Ok(Data {
89 kind,
90 data: data.remaining_buffer(),
91 range: segment_start..data.range().end,
92 })
93 }
94}