Coverage Report

Created: 2021-03-22 08:29

/src/wasm-tools/crates/wasmparser/src/readers/element_section.rs
Line
Count
Source (jump to first uncovered line)
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
16
use super::{
17
    BinaryReader, BinaryReaderError, InitExpr, Range, Result, SectionIteratorLimited,
18
    SectionReader, SectionWithLimitedItems, Type,
19
};
20
use crate::{ExternalKind, Operator};
21
22
0
#[derive(Clone)]
23
pub struct Element<'a> {
24
    pub kind: ElementKind<'a>,
25
    pub items: ElementItems<'a>,
26
    pub ty: Type,
27
}
28
29
0
#[derive(Clone)]
30
pub enum ElementKind<'a> {
31
    Passive,
32
    Active {
33
        table_index: u32,
34
        init_expr: InitExpr<'a>,
35
    },
36
    Declared,
37
}
38
39
0
#[derive(Debug, Copy, Clone)]
40
pub struct ElementItems<'a> {
41
    exprs: bool,
42
    offset: usize,
43
    data: &'a [u8],
44
}
45
46
#[derive(Debug)]
47
pub enum ElementItem {
48
    Null(Type),
49
    Func(u32),
50
}
51
52
impl<'a> ElementItems<'a> {
53
860k
    pub fn get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>>
54
860k
    where
55
860k
        'a: 'b,
56
860k
    {
57
860k
        ElementItemsReader::new(self.data, self.offset, self.exprs)
58
860k
    }
59
}
60
61
pub struct ElementItemsReader<'a> {
62
    reader: BinaryReader<'a>,
63
    count: u32,
64
    exprs: bool,
65
}
66
67
impl<'a> ElementItemsReader<'a> {
68
860k
    pub fn new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader> {
69
860k
        let mut reader = BinaryReader::new_with_offset(data, offset);
70
860k
        let count = reader.read_var_u32()?;
71
860k
        Ok(ElementItemsReader {
72
860k
            reader,
73
860k
            count,
74
860k
            exprs,
75
860k
        })
76
860k
    }
77
78
36.7M
    pub fn original_position(&self) -> usize {
79
36.7M
        self.reader.original_position()
80
36.7M
    }
81
82
1.60M
    pub fn get_count(&self) -> u32 {
83
1.60M
        self.count
84
1.60M
    }
85
86
2.02M
    pub fn uses_exprs(&self) -> bool {
87
2.02M
        self.exprs
88
2.02M
    }
89
90
38.6M
    pub fn read(&mut self) -> Result<ElementItem> {
91
38.6M
        if self.exprs {
92
35.2M
            let offset = self.reader.original_position();
93
35.2M
            let ret = match self.reader.read_operator()? {
94
35.2M
                Operator::RefNull { ty } => ElementItem::Null(ty),
95
41.0k
                Operator::RefFunc { function_index } => ElementItem::Func(function_index),
96
23
                _ => return Err(BinaryReaderError::new("invalid passive segment", offset)),
97
            };
98
35.2M
            match self.reader.read_operator()? {
99
35.2M
                Operator::End => {}
100
14
                _ => return Err(BinaryReaderError::new("invalid passive segment", offset)),
101
            }
102
35.2M
            Ok(ret)
103
        } else {
104
3.34M
            self.reader.read_var_u32().map(ElementItem::Func)
105
        }
106
38.6M
    }
107
}
108
109
impl<'a> IntoIterator for ElementItemsReader<'a> {
110
    type Item = Result<ElementItem>;
111
    type IntoIter = ElementItemsIterator<'a>;
112
    fn into_iter(self) -> Self::IntoIter {
113
        let count = self.count;
114
        ElementItemsIterator {
115
            reader: self,
116
            left: count,
117
            err: false,
118
        }
119
    }
120
}
121
122
pub struct ElementItemsIterator<'a> {
123
    reader: ElementItemsReader<'a>,
124
    left: u32,
125
    err: bool,
126
}
127
128
impl<'a> Iterator for ElementItemsIterator<'a> {
129
    type Item = Result<ElementItem>;
130
0
    fn next(&mut self) -> Option<Self::Item> {
131
0
        if self.err || self.left == 0 {
132
0
            return None;
133
0
        }
134
0
        let result = self.reader.read();
135
0
        self.err = result.is_err();
136
0
        self.left -= 1;
137
0
        Some(result)
138
0
    }
139
    fn size_hint(&self) -> (usize, Option<usize>) {
140
        let count = self.reader.get_count() as usize;
141
        (count, Some(count))
142
    }
143
}
144
145
151k
#[derive(Clone)]
146
pub struct ElementSectionReader<'a> {
147
    reader: BinaryReader<'a>,
148
    count: u32,
149
}
150
151
impl<'a> ElementSectionReader<'a> {
152
8.33M
    pub fn new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>> {
153
8.33M
        let mut reader = BinaryReader::new_with_offset(data, offset);
154
8.33M
        let count = reader.read_var_u32()?;
155
8.33M
        Ok(ElementSectionReader { reader, count })
156
8.33M
    }
157
158
748k
    pub fn original_position(&self) -> usize {
159
748k
        self.reader.original_position()
160
748k
    }
161
162
4.14M
    pub fn get_count(&self) -> u32 {
163
4.14M
        self.count
164
4.14M
    }
165
166
    /// Reads content of the element section.
167
    ///
168
    /// # Examples
169
    ///
170
    /// ```no_run
171
    /// # let data: &[u8] = &[];
172
    /// use wasmparser::{ElementSectionReader, ElementKind};
173
    /// let mut element_reader = ElementSectionReader::new(data, 0).unwrap();
174
    /// for _ in 0..element_reader.get_count() {
175
    ///     let element = element_reader.read().expect("element");
176
    ///     if let ElementKind::Active { init_expr, .. } = element.kind {
177
    ///         let mut init_expr_reader = init_expr.get_binary_reader();
178
    ///         let op = init_expr_reader.read_operator().expect("op");
179
    ///         println!("Init const: {:?}", op);
180
    ///     }
181
    ///     let mut items_reader = element.items.get_items_reader().expect("items reader");
182
    ///     for _ in 0..items_reader.get_count() {
183
    ///         let item = items_reader.read().expect("item");
184
    ///         println!("  Item: {:?}", item);
185
    ///     }
186
    /// }
187
    /// ```
188
870k
    pub fn read<'b>(&mut self) -> Result<Element<'b>>
189
870k
    where
190
870k
        'a: 'b,
191
870k
    {
192
870k
        let flags = self.reader.read_var_u32()?;
193
869k
        if (flags & !0b111) != 0 {
194
873
            return Err(BinaryReaderError::new(
195
873
                "invalid flags byte in element segment",
196
873
                self.reader.original_position() - 1,
197
873
            ));
198
868k
        }
199
868k
        let kind = if flags & 0b001 != 0 {
200
558k
            if flags & 0b010 != 0 {
201
213k
                ElementKind::Declared
202
            } else {
203
345k
                ElementKind::Passive
204
            }
205
        } else {
206
310k
            let table_index = if flags & 0b010 == 0 {
207
242k
                0
208
            } else {
209
67.2k
                self.reader.read_var_u32()?
210
            };
211
303k
            let init_expr = {
212
310k
                let expr_offset = self.reader.position;
213
310k
                self.reader.skip_init_expr()?;
214
303k
                let data = &self.reader.buffer[expr_offset..self.reader.position];
215
303k
                InitExpr::new(data, self.reader.original_offset + expr_offset)
216
303k
            };
217
303k
            ElementKind::Active {
218
303k
                table_index,
219
303k
                init_expr,
220
303k
            }
221
        };
222
862k
        let exprs = flags & 0b100 != 0;
223
862k
        let ty = if flags & 0b011 != 0 {
224
625k
            if exprs {
225
579k
                self.reader.read_type()?
226
            } else {
227
46.3k
                match self.reader.read_external_kind()? {
228
46.1k
                    ExternalKind::Function => Type::FuncRef,
229
                    _ => {
230
31
                        return Err(BinaryReaderError::new(
231
31
                            "only the function external type is supported in elem segment",
232
31
                            self.reader.original_position() - 1,
233
31
                        ));
234
                    }
235
                }
236
            }
237
        } else {
238
236k
            Type::FuncRef
239
        };
240
862k
        let data_start = self.reader.position;
241
862k
        let items_count = self.reader.read_var_u32()?;
242
862k
        if exprs {
243
35.2M
            for _ in 0..items_count {
244
35.2M
                self.reader.skip_init_expr()?;
245
            }
246
        } else {
247
3.36M
            for _ in 0..items_count {
248
3.36M
                self.reader.skip_var_32()?;
249
            }
250
        }
251
861k
        let data_end = self.reader.position;
252
861k
        let items = ElementItems {
253
861k
            offset: self.reader.original_offset + data_start,
254
861k
            data: &self.reader.buffer[data_start..data_end],
255
861k
            exprs,
256
861k
        };
257
861k
        Ok(Element { kind, items, ty })
258
870k
    }
259
}
260
261
impl<'a> SectionReader for ElementSectionReader<'a> {
262
    type Item = Element<'a>;
263
870k
    fn read(&mut self) -> Result<Self::Item> {
264
870k
        ElementSectionReader::read(self)
265
870k
    }
266
4.13M
    fn eof(&self) -> bool {
267
4.13M
        self.reader.eof()
268
4.13M
    }
269
748k
    fn original_position(&self) -> usize {
270
748k
        ElementSectionReader::original_position(self)
271
748k
    }
272
299k
    fn range(&self) -> Range {
273
299k
        self.reader.range()
274
299k
    }
275
}
276
277
impl<'a> SectionWithLimitedItems for ElementSectionReader<'a> {
278
4.14M
    fn get_count(&self) -> u32 {
279
4.14M
        ElementSectionReader::get_count(self)
280
4.14M
    }
281
}
282
283
impl<'a> IntoIterator for ElementSectionReader<'a> {
284
    type Item = Result<Element<'a>>;
285
    type IntoIter = SectionIteratorLimited<ElementSectionReader<'a>>;
286
287
3.99M
    fn into_iter(self) -> Self::IntoIter {
288
3.99M
        SectionIteratorLimited::new(self)
289
3.99M
    }
290
}