Skip to content

Commit 4d48ff9

Browse files
authored
Merge pull request mozilla#254 from mozilla/ipma-validate
Add more ipma validity checks
2 parents 0359c73 + eab3ba9 commit 4d48ff9

File tree

5 files changed

+48
-11
lines changed

5 files changed

+48
-11
lines changed

mp4parse/src/lib.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1977,14 +1977,25 @@ fn read_ipma<T: Read>(
19771977
U32::new(entry_count),
19781978
num_association_bytes,
19791979
)?;
1980-
let mut associations = TryVec::with_capacity(total_associations)?;
1980+
let mut associations = TryVec::<Association>::with_capacity(total_associations)?;
19811981

19821982
for _ in 0..entry_count {
19831983
let item_id = if version == 0 {
19841984
be_u16(src)?.into()
19851985
} else {
19861986
be_u32(src)?
19871987
};
1988+
1989+
if let Some(previous_association) = associations.last() {
1990+
if previous_association.item_id > item_id {
1991+
return Err(Error::InvalidData(
1992+
"Each ItemPropertyAssociation box shall be ordered by increasing item_ID",
1993+
));
1994+
} else if previous_association.item_id == item_id {
1995+
return Err(Error::InvalidData("There shall be at most one association box for each item_ID, in any ItemPropertyAssociation box"));
1996+
}
1997+
}
1998+
19881999
let association_count = src.read_u8()?;
19892000
for _ in 0..association_count {
19902001
let association = src
@@ -2000,6 +2011,23 @@ fn read_ipma<T: Read>(
20002011
})?;
20012012
}
20022013
}
2014+
2015+
check_parser_state!(src.content);
2016+
2017+
if version != 0 {
2018+
if let Some(Association {
2019+
item_id: max_item_id,
2020+
..
2021+
}) = associations.last()
2022+
{
2023+
if *max_item_id <= u16::MAX.into() {
2024+
return Err(Error::InvalidData(
2025+
"The version 0 should be used unless 32-bit item_ID values are needed",
2026+
));
2027+
}
2028+
}
2029+
}
2030+
20032031
Ok(associations)
20042032
}
20052033

435 Bytes
Binary file not shown.

mp4parse/tests/public.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
extern crate mp4parse as mp4;
66

7+
use mp4::Error;
78
use std::convert::TryInto;
89
use std::fs::File;
910
use std::io::{Cursor, Read};
@@ -29,11 +30,12 @@ static VIDEO_EME_CBCS_MP4: &str = "tests/bipbop_cbcs_video_init.mp4";
2930
static VIDEO_AV1_MP4: &str = "tests/tiny_av1.mp4";
3031
static IMAGE_AVIF: &str = "av1-avif/testFiles/Microsoft/Monochrome.avif";
3132
static IMAGE_AVIF_EXTENTS: &str = "tests/kodim-extents.avif";
32-
static IMAGE_AVIF_CORRUPT: &str = "tests/bug-1655846.avif";
33-
static IMAGE_AVIF_CORRUPT_2: &str = "tests/bug-1661347.avif";
33+
static IMAGE_AVIF_CORRUPT: &str = "tests/corrupt/bug-1655846.avif";
34+
static IMAGE_AVIF_CORRUPT_2: &str = "tests/corrupt/bug-1661347.avif";
35+
static IMAGE_AVIF_CORRUPT_3: &str = "tests/corrupt/bad-ipma-version.avif";
3436
static IMAGE_AVIF_GRID: &str = "av1-avif/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif";
3537
static AVIF_TEST_DIRS: &[&str] = &["tests", "av1-avif/testFiles"];
36-
static AVIF_CORRUPT_IMAGES: &[&str] = &[IMAGE_AVIF_CORRUPT, IMAGE_AVIF_CORRUPT_2];
38+
static AVIF_CORRUPT_IMAGES: &str = "tests/corrupt";
3739

3840
// Adapted from https://github.com/GuillaumeGomez/audio-video-metadata/blob/9dff40f565af71d5502e03a2e78ae63df95cfd40/src/metadata.rs#L53
3941
#[test]
@@ -641,6 +643,19 @@ fn public_avif_bug_1661347() {
641643
assert!(mp4::read_avif(input).is_err());
642644
}
643645

646+
#[test]
647+
fn public_avif_bad_ipma_version() {
648+
let input = &mut File::open(IMAGE_AVIF_CORRUPT_3).expect("Unknown file");
649+
let expected_msg = "The version 0 should be used unless 32-bit item_ID values are needed";
650+
match mp4::read_avif(input) {
651+
Err(Error::InvalidData(msg)) if msg == expected_msg => {}
652+
r => panic!(
653+
"Expected Err(Error::InvalidData({:?})), found {:?}",
654+
expected_msg, r
655+
),
656+
}
657+
}
658+
644659
#[test]
645660
#[ignore] // Remove when we add support; see https://github.com/mozilla/mp4parse-rust/issues/198
646661
fn public_avif_primary_item_is_grid() {
@@ -659,13 +674,7 @@ fn public_avif_read_samples() {
659674
eprintln!("Skipping {:?}", path);
660675
continue; // Skip directories, ReadMe.txt, etc.
661676
}
662-
if AVIF_CORRUPT_IMAGES
663-
.iter()
664-
.find(|&&corrupt| {
665-
std::fs::canonicalize(corrupt).unwrap() == path.canonicalize().unwrap()
666-
})
667-
.is_some()
668-
{
677+
if path.parent().unwrap() == Path::new(AVIF_CORRUPT_IMAGES) {
669678
eprintln!("Skipping {:?}", path);
670679
continue;
671680
}

0 commit comments

Comments
 (0)