flv: Hitting the end of the script data block is treated like the variable terminator.

Add a test case with real FLV data to enforce this.
This commit is contained in:
David Wendt 2023-04-18 21:14:11 -04:00 committed by kmeisthax
parent 4f831b4351
commit 4b81d65dc5
2 changed files with 109 additions and 7 deletions

View File

@ -1,4 +1,5 @@
use crate::reader::FlvReader;
use std::io::Seek;
fn parse_string<'a>(reader: &mut FlvReader<'a>, is_long_string: bool) -> Option<&'a [u8]> {
let length = if is_long_string {
@ -126,11 +127,18 @@ impl<'a> ScriptData<'a> {
///
/// No data size parameter is accepted; we parse until we reach an object
/// terminator, reach invalid data, or we run out of bytes in the reader.
pub fn parse(reader: &mut FlvReader<'a>) -> Option<Self> {
pub fn parse(reader: &mut FlvReader<'a>, data_size: u32) -> Option<Self> {
let start = reader.stream_position().expect("valid position");
let _trash = reader.read_u8()?;
let mut vars = vec![];
loop {
let cur_length = reader.stream_position().expect("valid position") - start;
if cur_length >= data_size as u64 {
// Terminators are commonly elided from script data blocks.
return Some(Self(vars));
}
let is_return = reader.peek_u24()?;
if is_return == 9 {
reader.read_u24()?;
@ -370,13 +378,13 @@ mod tests {
#[test]
fn read_scriptdata() {
let data = [
0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x06, 0x00, 0x03, 0x01, 0x02, 0x03, 0x05, 0x00, 0x00,
0x09,
0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x06, 0x00, 0x03, 0x01, 0x02, 0x03, 0x05, 0x00,
0x00, 0x09,
];
let mut reader = FlvReader::from_source(&data);
assert_eq!(
ScriptData::parse(&mut reader),
ScriptData::parse(&mut reader, 16),
Some(ScriptData(vec![
Variable {
name: &[0x01, 0x02, 0x03],

View File

@ -67,7 +67,7 @@ impl<'a> Tag<'a> {
18 => Tag {
timestamp,
stream_id,
data: TagData::Script(ScriptData::parse(reader)?),
data: TagData::Script(ScriptData::parse(reader, data_size)?),
},
_ => return None,
},
@ -157,8 +157,8 @@ mod tests {
fn read_tag_scriptdata() {
let data = [
0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
0x00, 0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x06, 0x00, 0x03, 0x01, 0x02, 0x03, 0x05, 0x00,
0x00, 0x09,
0x00, 0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x06, 0x00, 0x03, 0x01, 0x02, 0x03, 0x05,
0x00, 0x00, 0x09,
];
let mut reader = FlvReader::from_source(&data);
@ -180,4 +180,98 @@ mod tests {
})
)
}
#[test]
fn read_tag_onmetadata() {
let data = [
0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x0A, 0x6F, 0x6E, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61,
0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E, 0x00, 0x3F, 0xF1, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F, 0x00, 0x05, 0x77, 0x69,
0x64, 0x74, 0x68, 0x00, 0x40, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x6D, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0D, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x64, 0x61, 0x74, 0x61, 0x72, 0x61,
0x74, 0x65, 0x00, 0x40, 0x68, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x66,
0x72, 0x61, 0x6D, 0x65, 0x72, 0x61, 0x74, 0x65, 0x00, 0x40, 0x28, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0C, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x63, 0x6F, 0x64, 0x65,
0x63, 0x69, 0x64, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D,
0x61, 0x75, 0x64, 0x69, 0x6F, 0x64, 0x61, 0x74, 0x61, 0x72, 0x61, 0x74, 0x65, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x61, 0x75, 0x64, 0x69,
0x6F, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72, 0x61, 0x74, 0x65, 0x00, 0x40, 0xE5,
0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x61, 0x75, 0x64, 0x69, 0x6F, 0x73,
0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x40, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x73, 0x74, 0x65, 0x72, 0x65, 0x6F, 0x01, 0x00,
0x00, 0x0C, 0x61, 0x75, 0x64, 0x69, 0x6F, 0x63, 0x6F, 0x64, 0x65, 0x63, 0x69, 0x64,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x65, 0x6E, 0x63,
0x6F, 0x64, 0x65, 0x72, 0x02, 0x00, 0x0D, 0x4C, 0x61, 0x76, 0x66, 0x35, 0x38, 0x2E,
0x32, 0x31, 0x2E, 0x31, 0x30, 0x30, 0x00, 0x08, 0x66, 0x69, 0x6C, 0x65, 0x73, 0x69,
0x7A, 0x65, 0x00, 0x40, 0xCC, 0x73, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
];
let mut reader = FlvReader::from_source(&data);
assert_eq!(
Tag::parse(&mut reader),
Some(Tag {
timestamp: 0,
stream_id: 0,
data: TagData::Script(ScriptData(vec![Variable {
name: b"onMetaData",
data: Value::EcmaArray(vec![
Variable {
name: b"duration",
data: Value::Number(1.07)
},
Variable {
name: b"width",
data: Value::Number(320.0)
},
Variable {
name: b"height",
data: Value::Number(233.0)
},
Variable {
name: b"videodatarate",
data: Value::Number(195.3125)
},
Variable {
name: b"framerate",
data: Value::Number(12.0)
},
Variable {
name: b"videocodecid",
data: Value::Number(2.0)
},
Variable {
name: b"audiodatarate",
data: Value::Number(0.0)
},
Variable {
name: b"audiosamplerate",
data: Value::Number(44100.0)
},
Variable {
name: b"audiosamplesize",
data: Value::Number(16.0)
},
Variable {
name: b"stereo",
data: Value::Boolean(false)
},
Variable {
name: b"audiocodecid",
data: Value::Number(2.0)
},
Variable {
name: b"encoder",
data: Value::String(b"Lavf58.21.100")
},
Variable {
name: b"filesize",
data: Value::Number(14567.0)
}
])
}]))
})
)
}
}