Skip to content

Commit

Permalink
Fix a possible EOF issue given specific file content and memory buffe…
Browse files Browse the repository at this point in the history
…r size
  • Loading branch information
austinleroy committed Apr 4, 2024
1 parent 32b27da commit 5caf7a5
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ebml-iterable"
version = "0.6.1"
version = "0.6.2"
authors = ["Austin Blake <austinl3roy@gmail.com>"]
edition = "2018"
description = "This crate provides an iterator over EBML encoded data. The items provided by the iterator are Tags as defined in EBML. The iterator is spec-agnostic and requires a specification implementing specific traits to read files. Typically, you would only use this crate to implement a custom specification - most often you would prefer a crate providing an existing specification, like `webm-iterable`."
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ binary version of XML. It's used for container formats like [WebM][webm] or
```Cargo.toml
[dependencies]
ebml-iterable = "0.6.1"
ebml-iterable = "0.6.2"
```

# Usage
Expand Down
10 changes: 7 additions & 3 deletions src/tag_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,14 @@ impl<R: Read, TSpec> TagIterator<R, TSpec>
self.ensure_data_read(16)?;
let (tag_id, id_len) = self.peek_tag_id()?;
let spec_tag_type = <TSpec>::get_tag_data_type(tag_id);

let (size, size_len) = tools::read_vint(&self.buffer[(self.internal_buffer_position + id_len)..])
.or(Err(TagIteratorError::CorruptedFileData(CorruptedFileError::InvalidTagData{tag_id, position: self.current_offset() })))?
.ok_or(TagIteratorError::UnexpectedEOF { tag_start: self.current_offset(), tag_id: Some(tag_id), tag_size: None, partial_data: None })?;
.or(Err(TagIteratorError::CorruptedFileData(CorruptedFileError::InvalidTagData{tag_id, position: self.current_offset() })))?
.ok_or(TagIteratorError::UnexpectedEOF { tag_start: self.current_offset(), tag_id: Some(tag_id), tag_size: None, partial_data: None })?;

if self.buffered_byte_length <= id_len + size_len {
return Err(TagIteratorError::UnexpectedEOF { tag_start: self.current_offset(), tag_id: Some(tag_id), tag_size: None, partial_data: None });
}

if matches!(spec_tag_type, Some(TagDataType::UnsignedInt) | Some(TagDataType::Integer) | Some(TagDataType::Float)) && size > 8 {
return Err(TagIteratorError::CorruptedFileData(CorruptedFileError::InvalidTagData{tag_id, position: self.current_offset() }));
Expand Down
43 changes: 43 additions & 0 deletions tests/spec_write_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,49 @@ pub mod spec_write_read {
}
}

#[test]
pub fn eof_on_tag_size() {
let tags: Vec<TestSpec> = vec![
TestSpec::Segment(Master::Start),
TestSpec::TrackType(0x01),
TestSpec::Cluster(Master::Start),
TestSpec::CueRefCluster(3),
TestSpec::Count(1),
TestSpec::Block(vec![0, 1, 2, 3, 4, 5, 6, 7]),
TestSpec::Block(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]),
TestSpec::Cluster(Master::End),
TestSpec::Segment(Master::End),
];

let mut dest = Cursor::new(Vec::new());
let mut writer = TagWriter::new(&mut dest);

for tag in tags.iter() {
writer.write(tag).expect("Test shouldn't error");
}

println!("dest {:x?}", dest);

let mut src = Cursor::new(dest.get_ref()[0..31].to_vec());
let reader = TagIterator::with_capacity(&mut src, &[], 10);
let mut iter = reader.into_iter().skip_while(|x: &Result<TestSpec, TagIteratorError>| x.is_ok());

let err = iter.next().expect("Shouldn't have reached end of data");

match err.expect_err("Should be an error") {
TagIteratorError::UnexpectedEOF { tag_start, tag_id, tag_size, partial_data: _ } => {
println!("got error - {tag_start}, {tag_id:?}, {tag_size:?}");
assert_eq!(tag_start, 30);
assert_eq!(tag_id, Some(TestSpec::Block(vec![]).get_id()));
assert_eq!(tag_size, None);
},
other => {
println!("{other:?}");
assert!(false);
}
}
}

#[test]
pub fn allow_start_reading_not_at_root() {
let tags: Vec<TestSpec> = vec![
Expand Down

0 comments on commit 5caf7a5

Please sign in to comment.