@@ -1557,36 +1557,49 @@ fn read_iref<T: Read>(src: &mut BMFFBox<T>) -> Result<TryVec<SingleItemTypeRefer
1557
1557
1558
1558
fn read_iprp < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < AssociatedProperty > > {
1559
1559
let mut iter = src. box_iter ( ) ;
1560
- let mut properties = TryHashMap :: with_capacity ( 1 ) ?;
1561
- let mut associations = TryVec :: new ( ) ;
1560
+
1561
+ let properties = match iter. next_box ( ) ? {
1562
+ Some ( mut b) if b. head . name == BoxType :: ItemPropertyContainerBox => read_ipco ( & mut b) ,
1563
+ Some ( _) => Err ( Error :: InvalidData ( "unexpected iprp child" ) ) ,
1564
+ None => Err ( Error :: UnexpectedEOF ) ,
1565
+ } ?;
1566
+
1567
+ // Per ISO 23008-12:2017 § 9.3.1: There can be zero or more ipma boxes
1568
+ // but "There shall be at most one ItemPropertyAssociationbox with a given
1569
+ // pair of values of version and flags"
1570
+ let mut ipma_version_and_flag_values_seen = TryHashMap :: with_capacity ( 1 ) ?;
1571
+ let mut associated = TryVec :: new ( ) ;
1562
1572
1563
1573
while let Some ( mut b) = iter. next_box ( ) ? {
1564
- match b. head . name {
1565
- BoxType :: ItemPropertyContainerBox => {
1566
- properties = read_ipco ( & mut b) ?;
1567
- }
1568
- BoxType :: ItemPropertyAssociationBox => {
1569
- associations = read_ipma ( & mut b) ?;
1574
+ if b. head . name != BoxType :: ItemPropertyAssociationBox {
1575
+ return Err ( Error :: InvalidData ( "unexpected iprp child" ) ) ;
1576
+ }
1577
+
1578
+ let version_and_flags = read_fullbox_extra ( & mut b) ?;
1579
+ if ipma_version_and_flag_values_seen
1580
+ . insert ( version_and_flags, ( ) ) ?
1581
+ . is_some ( )
1582
+ {
1583
+ return Err ( Error :: InvalidData ( "Duplicate ipma with same version/flags" ) ) ;
1584
+ }
1585
+ let associations = read_ipma ( & mut b, version_and_flags) ?;
1586
+ for a in associations {
1587
+ if a. property_index == 0 {
1588
+ if a. essential {
1589
+ return Err ( Error :: InvalidData ( "0 property index can't be essential" ) ) ;
1590
+ }
1591
+ continue ;
1570
1592
}
1571
- _ => return Err ( Error :: InvalidData ( "unexpected ipco child" ) ) ,
1572
- }
1573
- }
1574
1593
1575
- let mut associated = TryVec :: new ( ) ;
1576
- for a in associations {
1577
- if a . property_index == 0 {
1578
- if a . essential {
1579
- return Err ( Error :: InvalidData ( "0 property index can't be essential" ) ) ;
1594
+ if let Some ( prop ) = properties . get ( & a . property_index ) {
1595
+ associated . push ( AssociatedProperty {
1596
+ item_id : a . item_id ,
1597
+ property : prop . try_clone ( ) ? ,
1598
+ } ) ? ;
1580
1599
}
1581
- continue ;
1582
1600
}
1583
1601
1584
- if let Some ( prop) = properties. get ( & a. property_index ) {
1585
- associated. push ( AssociatedProperty {
1586
- item_id : a. item_id ,
1587
- property : prop. try_clone ( ) ?,
1588
- } ) ?;
1589
- }
1602
+ check_parser_state ! ( b. content) ;
1590
1603
}
1591
1604
1592
1605
Ok ( associated)
@@ -1620,9 +1633,10 @@ pub struct AssociatedProperty {
1620
1633
pub property : ItemProperty ,
1621
1634
}
1622
1635
1623
- fn read_ipma < T : Read > ( src : & mut BMFFBox < T > ) -> Result < TryVec < Association > > {
1624
- let ( version, flags) = read_fullbox_extra ( src) ?;
1625
-
1636
+ fn read_ipma < T : Read > (
1637
+ src : & mut BMFFBox < T > ,
1638
+ ( version, flags) : ( u8 , u32 ) ,
1639
+ ) -> Result < TryVec < Association > > {
1626
1640
let mut associations = TryVec :: new ( ) ;
1627
1641
1628
1642
let entry_count = be_u32 ( src) ?;
0 commit comments