diff --git a/mp4parse/src/lib.rs b/mp4parse/src/lib.rs index 32d1ea75..f45df053 100644 --- a/mp4parse/src/lib.rs +++ b/mp4parse/src/lib.rs @@ -3697,7 +3697,7 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { read_dc_descriptor(descriptor, esds)?; } DECODER_SPECIFIC_TAG => { - read_ds_descriptor(descriptor, esds)?; + read_ds_descriptor(descriptor, esds, ParseStrictness::Permissive)?; } _ => { debug!("Unsupported descriptor, tag {}", tag); @@ -3723,7 +3723,11 @@ fn get_audio_object_type(bit_reader: &mut BitReader) -> Result { } /// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.7 and probably 14496-3 somewhere? -fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { +fn read_ds_descriptor( + data: &[u8], + esds: &mut ES_Descriptor, + strictness: ParseStrictness, +) -> Result<()> { #[cfg(feature = "mp4v")] // Check if we are in a Visual esda Box. if esds.video_codec != CodecType::Unknown { @@ -3823,9 +3827,18 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { }; bit_reader.skip(1)?; // frameLengthFlag - let depend_on_core_order: u8 = ReadInto::read(bit_reader, 1)?; - if depend_on_core_order > 0 { - bit_reader.skip(14)?; // codeCoderDelay + let depends_on_core_coder: u8 = ReadInto::read(bit_reader, 1)?; + if depends_on_core_coder > 0 { + if bit_reader.remaining() < 14 { + fail_if( + strictness != ParseStrictness::Permissive, + "The GASpecificConfig 'coreCoderDelay' field shall be present \ + if 'dependsOnCoreCoder' is set per MPEG-4 Audio (ISO 14496-3:2019) § 4.4.1", + )?; + debug!("Insufficient bits for coreCoderDelay, ignoring dependsOnCoreCoder"); + } else { + bit_reader.skip(14)?; // coreCoderDelay + } } bit_reader.skip(1)?; // extensionFlag diff --git a/mp4parse/src/tests.rs b/mp4parse/src/tests.rs index 56b739c6..405fd87f 100644 --- a/mp4parse/src/tests.rs +++ b/mp4parse/src/tests.rs @@ -1236,6 +1236,30 @@ fn read_esds_invalid_descriptor() { } } +#[test] +fn read_esds_depends_on_core_coder_invalid() { + // dependsOnCoreCoder flag is set, but coreCoderDelay bits are not present. + // Extracted from BMO #1709329 audio-stripped.m4a using Bento4. + // "mp4extract --payload-only moov/trak/mdia/minf/stbl/stsd/mp4a/esds audio-stripped.m4a /dev/stdout | xxd -i -c 15" + let esds = vec![ + 0x03, 0x80, 0x80, 0x80, 0x22, 0x00, 0x01, 0x00, 0x04, 0x80, 0x80, 0x80, 0x14, 0x40, 0x15, + 0x00, 0x02, 0x15, 0x00, 0x02, 0x04, 0x88, 0x00, 0x01, 0xea, 0x64, 0x05, 0x80, 0x80, 0x80, + 0x02, 0x12, 0x12, 0x06, 0x80, 0x80, 0x80, 0x01, 0x02, + ]; + + let mut stream = make_box(BoxSize::Auto, b"esds", |s| { + s.B32(0) // reserved + .append_bytes(esds.as_slice()) + }); + let mut iter = super::BoxIter::new(&mut stream); + let mut stream = iter.next_box().unwrap().unwrap(); + + match super::read_esds(&mut stream) { + Ok(esds) => assert_eq!(esds.audio_codec, super::CodecType::AAC), + _ => panic!("unexpected result with invalid descriptor"), + } +} + #[test] fn read_esds_redundant_descriptor() { // the '2' at the end is redundant data.