Skip to content

Commit ac4fc48

Browse files
committed
EBML: Support locking the ElementReader to the current master
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
1 parent 9a28736 commit ac4fc48

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

src/ebml/element_reader.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ ebml_master_elements! {
148148
}
149149

150150
struct ElementReaderContext {
151+
/// Previous master element
152+
previous_master: Option<MasterElement>,
151153
/// Current master element
152154
current_master: Option<MasterElement>,
153155
/// Remaining length of the master element
@@ -156,17 +158,24 @@ struct ElementReaderContext {
156158
max_id_length: u8,
157159
/// Maximum size in octets of all element data sizes
158160
max_size_length: u8,
161+
/// Whether the reader is locked to the current master element
162+
///
163+
/// This is set with [`ElementReader::lock`], and is used to prevent
164+
/// the reader from reading past the end of the current master element.
165+
locked: bool,
159166
}
160167

161168
impl Default for ElementReaderContext {
162169
fn default() -> Self {
163170
Self {
171+
previous_master: None,
164172
current_master: None,
165173
master_length: 0,
166174
// https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxidlength-element
167175
max_id_length: 4,
168176
// https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxsizelength-element
169177
max_size_length: 8,
178+
locked: false,
170179
}
171180
}
172181
}
@@ -213,6 +222,7 @@ where
213222
return Ok(ElementReaderYield::Unknown(header));
214223
};
215224

225+
self.ctx.previous_master = self.ctx.current_master;
216226
self.ctx.current_master = Some(*master);
217227
self.ctx.master_length = header.size.value();
218228
Ok(ElementReaderYield::Master((
@@ -221,12 +231,34 @@ where
221231
)))
222232
}
223233

234+
/// Lock the reader to the current master element
235+
pub(crate) fn lock(&mut self) {
236+
self.ctx.locked = true;
237+
}
238+
239+
pub(crate) fn unlock(&mut self) {
240+
self.ctx.locked = false;
241+
}
242+
243+
pub(crate) fn goto_previous_master(&mut self) -> Result<()> {
244+
if let Some(previous_master) = self.ctx.previous_master {
245+
self.ctx.current_master = Some(previous_master);
246+
Ok(())
247+
} else {
248+
decode_err!(@BAIL Ebml, "Expected a parent element to be available")
249+
}
250+
}
251+
224252
pub(crate) fn next(&mut self) -> Result<ElementReaderYield> {
225253
let Some(current_master) = self.ctx.current_master else {
226254
return self.next_master();
227255
};
228256

229257
if self.ctx.master_length == 0 {
258+
if self.ctx.locked {
259+
return Ok(ElementReaderYield::Eof);
260+
}
261+
230262
return self.next_master();
231263
}
232264

@@ -244,6 +276,21 @@ where
244276
return Ok(ElementReaderYield::Unknown(header));
245277
};
246278

279+
if child.data_type == ElementDataType::Master {
280+
self.ctx.current_master = Some(
281+
*MASTER_ELEMENTS
282+
.get(&header.id)
283+
.expect("Nested master elements should be defined at this level."),
284+
);
285+
self.ctx.master_length = header.size.value();
286+
287+
// We encountered a nested master element
288+
return Ok(ElementReaderYield::Master((
289+
child.ident,
290+
header.size.value(),
291+
)));
292+
}
293+
247294
Ok(ElementReaderYield::Child((*child, header.size.value())))
248295
}
249296

0 commit comments

Comments
 (0)