ID3v2: Validate size before and after reading additional flag data

This commit is contained in:
Serial 2023-04-23 15:19:13 -04:00 committed by Alex
parent cf2488d5d5
commit 55bcd467eb
3 changed files with 25 additions and 0 deletions

View file

@ -27,18 +27,30 @@ impl<'a> Frame<'a> {
// Get the encryption method symbol
if let Some(enc) = flags.encryption.as_mut() {
if size < 1 {
return Err(Id3v2Error::new(Id3v2ErrorKind::BadFrameLength).into());
}
*enc = reader.read_u8()?;
size -= 1;
}
// Get the group identifier
if let Some(group) = flags.grouping_identity.as_mut() {
if size < 1 {
return Err(Id3v2Error::new(Id3v2ErrorKind::BadFrameLength).into());
}
*group = reader.read_u8()?;
size -= 1;
}
// Get the real data length
if flags.data_length_indicator.is_some() || flags.compression {
if size < 4 {
return Err(Id3v2Error::new(Id3v2ErrorKind::BadFrameLength).into());
}
// For some reason, no one can follow the spec, so while a data length indicator is *written*
// the flag **isn't always set**
let len = reader.read_u32::<BigEndian>()?.unsynch();
@ -72,6 +84,11 @@ impl<'a> Frame<'a> {
return Err(Id3v2Error::new(Id3v2ErrorKind::CompressedFrameEncountered).into());
}
// Frames must have at least 1 byte, *after* all of the additional data flags can provide
if size == 0 {
return Err(Id3v2Error::new(Id3v2ErrorKind::BadFrameLength).into());
}
let value = if flags.encryption.is_some() {
if flags.data_length_indicator.is_none() {
return Err(Id3v2Error::new(Id3v2ErrorKind::MissingDataLengthIndicator).into());

View file

@ -10,6 +10,14 @@ fn crash1() {
let _ = MpegFile::read_from(&mut reader, ParseOptions::new());
}
#[test]
fn crash2() {
let mut reader =
get_reader("mpegfile_read_from/crash-718f75611e77caac968c7f68cdefa1472172f64b");
let _ = MpegFile::read_from(&mut reader, ParseOptions::new());
}
#[test]
fn oom1() {
oom_test::<MpegFile>("mpegfile_read_from/oom-f8730cbfa5682ab12343ccb70de9b71a061ef4d0");