@@ -14,9 +14,9 @@ extern crate bitreader;
14
14
extern crate num_traits;
15
15
use byteorder:: { ReadBytesExt , WriteBytesExt } ;
16
16
use bitreader:: { BitReader , ReadInto } ;
17
+ use std:: convert:: TryInto as _;
17
18
use std:: io:: { Read , Take } ;
18
19
use std:: io:: Cursor ;
19
- use std:: cmp;
20
20
use num_traits:: Num ;
21
21
22
22
#[ cfg( feature = "mp4parse_fallible" ) ]
@@ -42,6 +42,46 @@ const BUF_SIZE_LIMIT: usize = 10 * 1024 * 1024;
42
42
// frame per table entry in 30 fps.
43
43
const TABLE_SIZE_LIMIT : u32 = 30 * 60 * 60 * 24 * 7 ;
44
44
45
+ /// A trait to indicate a type can be infallibly converted to `u64`.
46
+ /// This should only be implemented for infallible conversions, so only unsigned types are valid.
47
+ trait ToU64 {
48
+ fn to_u64 ( self ) -> u64 ;
49
+ }
50
+
51
+ /// Statically verify that the platform `usize` can fit within a `u64`.
52
+ /// If the size won't fit on the given platform, this will fail at compile time, but if a type
53
+ /// which can fail TryInto<usize> is used, it may panic.
54
+ impl ToU64 for usize {
55
+ fn to_u64 ( self ) -> u64 {
56
+ static_assertions:: const_assert!( std:: mem:: size_of:: <usize >( ) <= std:: mem:: size_of:: <u64 >( ) ) ;
57
+ self . try_into ( ) . expect ( "usize -> u64 conversion failed" )
58
+ }
59
+ }
60
+
61
+ /// A trait to indicate a type can be infallibly converted to `usize`.
62
+ /// This should only be implemented for infallible conversions, so only unsigned types are valid.
63
+ trait ToUsize {
64
+ fn to_usize ( self ) -> usize ;
65
+ }
66
+
67
+ /// Statically verify that the given type can fit within a `usize`.
68
+ /// If the size won't fit on the given platform, this will fail at compile time, but if a type
69
+ /// which can fail TryInto<usize> is used, it may panic.
70
+ macro_rules! impl_to_usize_from {
71
+ ( $from_type: ty ) => {
72
+ impl ToUsize for $from_type {
73
+ fn to_usize( self ) -> usize {
74
+ static_assertions:: const_assert!( std:: mem:: size_of:: <$from_type>( ) <= std:: mem:: size_of:: <usize >( ) ) ;
75
+ self . try_into( ) . expect( concat!( stringify!( $from_type) , " -> usize conversion failed" ) )
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ impl_to_usize_from ! ( u8 ) ;
82
+ impl_to_usize_from ! ( u16 ) ;
83
+ impl_to_usize_from ! ( u32 ) ;
84
+
45
85
// TODO: vec_push() needs to be replaced when Rust supports fallible memory
46
86
// allocation in raw_vec.
47
87
#[ allow( unreachable_code) ]
@@ -109,6 +149,12 @@ impl From<std::string::FromUtf8Error> for Error {
109
149
}
110
150
}
111
151
152
+ impl From < std:: num:: TryFromIntError > for Error {
153
+ fn from ( _: std:: num:: TryFromIntError ) -> Error {
154
+ Error :: Unsupported ( "integer conversion failed" )
155
+ }
156
+ }
157
+
112
158
impl From < ( ) > for Error {
113
159
fn from ( _: ( ) ) -> Error {
114
160
Error :: OutOfMemory
@@ -728,12 +774,12 @@ impl Track {
728
774
}
729
775
}
730
776
731
- struct BMFFBox < ' a , T : ' a + Read > {
777
+ struct BMFFBox < ' a , T : ' a > {
732
778
head : BoxHeader ,
733
779
content : Take < & ' a mut T > ,
734
780
}
735
781
736
- struct BoxIter < ' a , T : ' a + Read > {
782
+ struct BoxIter < ' a , T : ' a > {
737
783
src : & ' a mut T ,
738
784
}
739
785
@@ -762,8 +808,8 @@ impl<'a, T: Read> Read for BMFFBox<'a, T> {
762
808
}
763
809
764
810
impl < ' a , T : Read > BMFFBox < ' a , T > {
765
- fn bytes_left ( & self ) -> usize {
766
- self . content . limit ( ) as usize
811
+ fn bytes_left ( & self ) -> u64 {
812
+ self . content . limit ( )
767
813
}
768
814
769
815
fn get_header ( & self ) -> & BoxHeader {
@@ -775,7 +821,7 @@ impl<'a, T: Read> BMFFBox<'a, T> {
775
821
}
776
822
}
777
823
778
- impl < ' a , T : Read > Drop for BMFFBox < ' a , T > {
824
+ impl < ' a , T > Drop for BMFFBox < ' a , T > {
779
825
fn drop ( & mut self ) {
780
826
if self . content . limit ( ) > 0 {
781
827
let name: FourCC = From :: from ( self . head . name ) ;
@@ -814,7 +860,7 @@ fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Result<BoxHeader> {
814
860
if size >= offset + 16 {
815
861
let mut buffer = [ 0u8 ; 16 ] ;
816
862
let count = src. read ( & mut buffer) ?;
817
- offset += count as u64 ;
863
+ offset += count. to_u64 ( ) ;
818
864
if count == 16 {
819
865
Some ( buffer)
820
866
} else {
@@ -853,7 +899,7 @@ fn skip_box_content<T: Read>(src: &mut BMFFBox<T>) -> Result<()> {
853
899
let to_skip = {
854
900
let header = src. get_header ( ) ;
855
901
debug ! ( "{:?} (skipped)" , header) ;
856
- ( header. size - header. offset ) as usize
902
+ header. size . checked_sub ( header. offset ) . expect ( "header offset > size" )
857
903
} ;
858
904
assert_eq ! ( to_skip, src. bytes_left( ) ) ;
859
905
skip ( src, to_skip)
@@ -974,7 +1020,7 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: &mut MediaContext) -> Result<
974
1020
}
975
1021
976
1022
fn read_pssh < T : Read > ( src : & mut BMFFBox < T > ) -> Result < ProtectionSystemSpecificHeaderBox > {
977
- let len = src. bytes_left ( ) ;
1023
+ let len = src. bytes_left ( ) . try_into ( ) ? ;
978
1024
let mut box_content = read_buf ( src, len) ?;
979
1025
let ( system_id, kid, data) = {
980
1026
let pssh = & mut Cursor :: new ( box_content. as_slice ( ) ) ;
@@ -992,14 +1038,14 @@ fn read_pssh<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSystemSpecificHe
992
1038
}
993
1039
}
994
1040
995
- let data_size = be_u32_with_limit ( pssh) ? as usize ;
1041
+ let data_size = be_u32_with_limit ( pssh) ?. to_usize ( ) ;
996
1042
let data = read_buf ( pssh, data_size) ?;
997
1043
998
1044
( system_id, kid, data)
999
1045
} ;
1000
1046
1001
1047
let mut pssh_box = Vec :: new ( ) ;
1002
- write_be_u32 ( & mut pssh_box, src. head . size as u32 ) ?;
1048
+ write_be_u32 ( & mut pssh_box, src. head . size . try_into ( ) ? ) ?;
1003
1049
pssh_box. extend_from_slice ( b"pssh" ) ;
1004
1050
pssh_box. append ( & mut box_content) ;
1005
1051
@@ -1456,9 +1502,9 @@ fn read_stsc<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleToChunkBox> {
1456
1502
fn read_ctts < T : Read > ( src : & mut BMFFBox < T > ) -> Result < CompositionOffsetBox > {
1457
1503
let ( version, _) = read_fullbox_extra ( src) ?;
1458
1504
1459
- let counts = be_u32_with_limit ( src) ?;
1505
+ let counts = u64 :: from ( be_u32_with_limit ( src) ?) ;
1460
1506
1461
- if src. bytes_left ( ) < ( counts as usize * 8 ) {
1507
+ if src. bytes_left ( ) < counts . checked_mul ( 8 ) . expect ( " counts -> bytes overflow" ) {
1462
1508
return Err ( Error :: InvalidData ( "insufficient data in 'ctts' box" ) ) ;
1463
1509
}
1464
1510
@@ -1588,7 +1634,7 @@ fn read_vpcc<T: Read>(src: &mut BMFFBox<T>) -> Result<VPxConfigBox> {
1588
1634
} ;
1589
1635
1590
1636
let codec_init_size = be_u16 ( src) ?;
1591
- let codec_init = read_buf ( src, codec_init_size as usize ) ?;
1637
+ let codec_init = read_buf ( src, codec_init_size. to_usize ( ) ) ?;
1592
1638
1593
1639
// TODO(rillian): validate field value ranges.
1594
1640
Ok ( VPxConfigBox {
@@ -1636,7 +1682,7 @@ fn read_av1c<T: Read>(src: &mut BMFFBox<T>) -> Result<AV1ConfigBox> {
1636
1682
} ;
1637
1683
1638
1684
let config_obus_size = src. bytes_left ( ) ;
1639
- let config_obus = read_buf ( src, config_obus_size as usize ) ?;
1685
+ let config_obus = read_buf ( src, config_obus_size. try_into ( ) ? ) ?;
1640
1686
1641
1687
Ok ( AV1ConfigBox {
1642
1688
profile,
@@ -1657,11 +1703,11 @@ fn read_flac_metadata<T: Read>(src: &mut BMFFBox<T>) -> Result<FLACMetadataBlock
1657
1703
let temp = src. read_u8 ( ) ?;
1658
1704
let block_type = temp & 0x7f ;
1659
1705
let length = be_u24 ( src) ?;
1660
- if length as usize > src. bytes_left ( ) {
1706
+ if u64 :: from ( length) > src. bytes_left ( ) {
1661
1707
return Err ( Error :: InvalidData (
1662
1708
"FLACMetadataBlock larger than parent box" ) ) ;
1663
1709
}
1664
- let data = read_buf ( src, length as usize ) ?;
1710
+ let data = read_buf ( src, length. to_usize ( ) ) ?;
1665
1711
Ok ( FLACMetadataBlock {
1666
1712
block_type,
1667
1713
data,
@@ -1684,7 +1730,7 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
1684
1730
let mut end: u32 = 0 ; // It's u8 without declaration type that is incorrect.
1685
1731
// MSB of extend_or_len indicates more bytes, up to 4 bytes.
1686
1732
for _ in 0 ..4 {
1687
- if ( des. position ( ) as usize ) == remains. len ( ) {
1733
+ if des. position ( ) == remains. len ( ) . to_u64 ( ) {
1688
1734
// There's nothing more to read, the 0x80 was actually part of
1689
1735
// the content, and not an extension size.
1690
1736
end = des. position ( ) as u32 ;
@@ -1698,11 +1744,11 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
1698
1744
}
1699
1745
} ;
1700
1746
1701
- if ( end as usize ) > remains. len ( ) || u64:: from ( end) < des. position ( ) {
1747
+ if end. to_usize ( ) > remains. len ( ) || u64:: from ( end) < des. position ( ) {
1702
1748
return Err ( Error :: InvalidData ( "Invalid descriptor." ) ) ;
1703
1749
}
1704
1750
1705
- let descriptor = & remains[ des. position ( ) as usize .. end as usize ] ;
1751
+ let descriptor = & remains[ des. position ( ) . try_into ( ) ? .. end. to_usize ( ) ] ;
1706
1752
1707
1753
match tag {
1708
1754
ESDESCR_TAG => {
@@ -1719,7 +1765,7 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
1719
1765
} ,
1720
1766
}
1721
1767
1722
- remains = & remains[ end as usize .. remains. len ( ) ] ;
1768
+ remains = & remains[ end. to_usize ( ) .. remains. len ( ) ] ;
1723
1769
}
1724
1770
1725
1771
Ok ( ( ) )
@@ -1897,8 +1943,8 @@ fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
1897
1943
// Skip uninteresting fields.
1898
1944
skip ( des, 12 ) ?;
1899
1945
1900
- if data. len ( ) > des. position ( ) as usize {
1901
- find_descriptor ( & data[ des. position ( ) as usize .. data. len ( ) ] , esds) ?;
1946
+ if data. len ( ) . to_u64 ( ) > des. position ( ) {
1947
+ find_descriptor ( & data[ des. position ( ) . try_into ( ) ? .. data. len ( ) ] , esds) ?;
1902
1948
}
1903
1949
1904
1950
esds. audio_codec = match object_profile {
@@ -1926,12 +1972,12 @@ fn read_es_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
1926
1972
// Url flag, second bit from left most.
1927
1973
if esds_flags & 0x40 > 0 {
1928
1974
// Skip uninteresting fields.
1929
- let skip_es_len: usize = des. read_u8 ( ) ? as usize + 2 ;
1975
+ let skip_es_len = u64 :: from ( des. read_u8 ( ) ?) + 2 ;
1930
1976
skip ( des, skip_es_len) ?;
1931
1977
}
1932
1978
1933
- if data. len ( ) > des. position ( ) as usize {
1934
- find_descriptor ( & data[ des. position ( ) as usize .. data. len ( ) ] , esds) ?;
1979
+ if data. len ( ) . to_u64 ( ) > des. position ( ) {
1980
+ find_descriptor ( & data[ des. position ( ) . try_into ( ) ? .. data. len ( ) ] , esds) ?;
1935
1981
}
1936
1982
1937
1983
Ok ( ( ) )
@@ -1942,8 +1988,8 @@ fn read_esds<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> {
1942
1988
1943
1989
// Subtract 4 extra to offset the members of fullbox not accounted for in
1944
1990
// head.offset
1945
- let esds_size = src. head . size - src. head . offset - 4 ;
1946
- let esds_array = read_buf ( src, esds_size as usize ) ?;
1991
+ let esds_size = src. head . size . checked_sub ( src. head . offset + 4 ) . expect ( "offset invalid" ) ;
1992
+ let esds_array = read_buf ( src, esds_size. try_into ( ) ? ) ?;
1947
1993
1948
1994
let mut es_data = ES_Descriptor :: default ( ) ;
1949
1995
find_descriptor ( & esds_array, & mut es_data) ?;
@@ -2002,7 +2048,7 @@ fn read_dops<T: Read>(src: &mut BMFFBox<T>) -> Result<OpusSpecificBox> {
2002
2048
} else {
2003
2049
let stream_count = src. read_u8 ( ) ?;
2004
2050
let coupled_count = src. read_u8 ( ) ?;
2005
- let channel_mapping = read_buf ( src, output_channel_count as usize ) ?;
2051
+ let channel_mapping = read_buf ( src, output_channel_count. to_usize ( ) ) ?;
2006
2052
2007
2053
Some ( ChannelMappingTable {
2008
2054
stream_count,
@@ -2076,10 +2122,10 @@ fn read_alac<T: Read>(src: &mut BMFFBox<T>) -> Result<ALACSpecificBox> {
2076
2122
return Err ( Error :: InvalidData ( "no-zero alac (ALAC) flags" ) ) ;
2077
2123
}
2078
2124
2079
- let length = src. bytes_left ( ) ;
2080
- if length != 24 && length != 48 {
2081
- return Err ( Error :: InvalidData ( "ALACSpecificBox magic cookie is the wrong size" ) ) ;
2082
- }
2125
+ let length = match src. bytes_left ( ) {
2126
+ x @ 24 | x @ 48 => x . try_into ( ) . expect ( "infallible conversion to usize" ) ,
2127
+ _ => return Err ( Error :: InvalidData ( "ALACSpecificBox magic cookie is the wrong size" ) ) ,
2128
+ } ;
2083
2129
let data = read_buf ( src, length) ?;
2084
2130
2085
2131
Ok ( ALACSpecificBox {
@@ -2151,8 +2197,8 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
2151
2197
codec_specific. is_some ( ) {
2152
2198
return Err ( Error :: InvalidData ( "malformed video sample entry" ) ) ;
2153
2199
}
2154
- let avcc_size = b. head . size - b. head . offset ;
2155
- let avcc = read_buf ( & mut b. content , avcc_size as usize ) ?;
2200
+ let avcc_size = b. head . size . checked_sub ( b. head . offset ) . expect ( "offset invalid" ) ;
2201
+ let avcc = read_buf ( & mut b. content , avcc_size. try_into ( ) ? ) ?;
2156
2202
debug ! ( "{:?} (avcc)" , avcc) ;
2157
2203
// TODO(kinetik): Parse avcC box? For now we just stash the data.
2158
2204
codec_specific = Some ( VideoCodecSpecific :: AVCConfig ( avcc) ) ;
@@ -2181,8 +2227,8 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
2181
2227
let ( _, _) = read_fullbox_extra ( & mut b. content ) ?;
2182
2228
// Subtract 4 extra to offset the members of fullbox not
2183
2229
// accounted for in head.offset
2184
- let esds_size = b. head . size - b. head . offset - 4 ;
2185
- let esds = read_buf ( & mut b. content , esds_size as usize ) ?;
2230
+ let esds_size = b. head . size . checked_sub ( b. head . offset + 4 ) . expect ( "offset invalid" ) ;
2231
+ let esds = read_buf ( & mut b. content , esds_size. try_into ( ) ? ) ?;
2186
2232
codec_specific = Some ( VideoCodecSpecific :: ESDSConfig ( esds) ) ;
2187
2233
}
2188
2234
BoxType :: ProtectionSchemeInformationBox => {
@@ -2385,7 +2431,7 @@ fn read_stsd<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> Result<SampleD
2385
2431
} ;
2386
2432
vec_push ( & mut descriptions, description) ?;
2387
2433
check_parser_state ! ( b. content) ;
2388
- if descriptions. len ( ) == description_count as usize {
2434
+ if descriptions. len ( ) == description_count. to_usize ( ) {
2389
2435
break ;
2390
2436
}
2391
2437
}
@@ -2467,7 +2513,7 @@ fn read_tenc<T: Read>(src: &mut BMFFBox<T>) -> Result<TrackEncryptionBox> {
2467
2513
let default_constant_iv = match ( default_is_encrypted, default_iv_size) {
2468
2514
( 1 , 0 ) => {
2469
2515
let default_constant_iv_size = src. read_u8 ( ) ?;
2470
- Some ( read_buf ( src, default_constant_iv_size as usize ) ?)
2516
+ Some ( read_buf ( src, default_constant_iv_size. to_usize ( ) ) ?)
2471
2517
} ,
2472
2518
_ => None ,
2473
2519
} ;
@@ -2661,23 +2707,14 @@ fn read_ilst_multiple_u8_data<T: Read>(src: &mut BMFFBox<T>) -> Result<Vec<Vec<u
2661
2707
2662
2708
fn read_ilst_data < T : Read > ( src : & mut BMFFBox < T > ) -> Result < Vec < u8 > > {
2663
2709
// Skip past the padding bytes
2664
- skip ( & mut src. content , src. head . offset as usize ) ?;
2665
- let size = src. content . limit ( ) as usize ;
2710
+ skip ( & mut src. content , src. head . offset ) ?;
2711
+ let size = src. content . limit ( ) . try_into ( ) ? ;
2666
2712
read_buf ( & mut src. content , size)
2667
2713
}
2668
2714
2669
2715
/// Skip a number of bytes that we don't care to parse.
2670
- fn skip < T : Read > ( src : & mut T , mut bytes : usize ) -> Result < ( ) > {
2671
- const BUF_SIZE : usize = 64 * 1024 ;
2672
- let mut buf = vec ! [ 0 ; BUF_SIZE ] ;
2673
- while bytes > 0 {
2674
- let buf_size = cmp:: min ( bytes, BUF_SIZE ) ;
2675
- let len = src. take ( buf_size as u64 ) . read ( & mut buf) ?;
2676
- if len == 0 {
2677
- return Err ( Error :: UnexpectedEOF ) ;
2678
- }
2679
- bytes -= len;
2680
- }
2716
+ fn skip < T : Read > ( src : & mut T , bytes : u64 ) -> Result < ( ) > {
2717
+ std:: io:: copy ( & mut src. take ( bytes) , & mut std:: io:: sink ( ) ) ?;
2681
2718
Ok ( ( ) )
2682
2719
}
2683
2720
@@ -2714,9 +2751,7 @@ fn be_u16<T: ReadBytesExt>(src: &mut T) -> Result<u16> {
2714
2751
}
2715
2752
2716
2753
fn be_u24 < T : ReadBytesExt > ( src : & mut T ) -> Result < u32 > {
2717
- src. read_uint :: < byteorder:: BigEndian > ( 3 )
2718
- . map ( |v| v as u32 )
2719
- . map_err ( From :: from)
2754
+ src. read_u24 :: < byteorder:: BigEndian > ( ) . map_err ( From :: from)
2720
2755
}
2721
2756
2722
2757
fn be_u32 < T : ReadBytesExt > ( src : & mut T ) -> Result < u32 > {
0 commit comments