Skip to content

Commit c378c16

Browse files
committed
Remove artificial allocation limit (TABLE_SIZE_LIMIT).
This was an early attempt at preemptively limiting some potentially large allocations to avoid OOM panic situations. These situations are now better handled via [`fallible_collections`](https://github.com/vcombey/fallible_collections). Fixes #310.
1 parent 1c5dc60 commit c378c16

File tree

3 files changed

+15
-47
lines changed

3 files changed

+15
-47
lines changed

mp4parse/src/lib.rs

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ pub mod unstable;
4747
// Arbitrary buffer size limit used for raw read_bufs on a box.
4848
const BUF_SIZE_LIMIT: u64 = 10 * 1024 * 1024;
4949

50-
// Max table length. Calculating in worst case for one week long video, one
51-
// frame per table entry in 30 fps.
52-
const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24 * 7;
53-
5450
/// The 'mif1' brand indicates structural requirements on files
5551
/// See HEIF (ISO 23008-12:2017) § 10.2.1
5652
const MIF1_BRAND: FourCC = FourCC { value: *b"mif1" };
@@ -2958,14 +2954,14 @@ fn read_pssh<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSystemSpecificHe
29582954

29592955
let mut kid = TryVec::<ByteData>::new();
29602956
if version > 0 {
2961-
let count = be_u32_with_limit(pssh)?;
2957+
let count = be_u32(pssh)?;
29622958
for _ in 0..count {
29632959
let item = read_buf(pssh, 16)?;
29642960
kid.push(item)?;
29652961
}
29662962
}
29672963

2968-
let data_size = be_u32_with_limit(pssh)?;
2964+
let data_size = be_u32(pssh)?;
29692965
let data = read_buf(pssh, data_size.into())?;
29702966

29712967
(system_id, kid, data)
@@ -3296,7 +3292,7 @@ fn read_tkhd<T: Read>(src: &mut BMFFBox<T>) -> Result<TrackHeaderBox> {
32963292
/// See ISOBMFF (ISO 14496-12:2015) § 8.6.6
32973293
fn read_elst<T: Read>(src: &mut BMFFBox<T>) -> Result<EditListBox> {
32983294
let (version, _) = read_fullbox_extra(src)?;
3299-
let edit_count = be_u32_with_limit(src)?;
3295+
let edit_count = be_u32(src)?;
33003296
let mut edits = TryVec::with_capacity(edit_count.to_usize())?;
33013297
for _ in 0..edit_count {
33023298
let (segment_duration, media_time) = match version {
@@ -3372,7 +3368,7 @@ fn read_mdhd<T: Read>(src: &mut BMFFBox<T>) -> Result<MediaHeaderBox> {
33723368
/// See ISOBMFF (ISO 14496-12:2015) § 8.7.5
33733369
fn read_stco<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
33743370
let (_, _) = read_fullbox_extra(src)?;
3375-
let offset_count = be_u32_with_limit(src)?;
3371+
let offset_count = be_u32(src)?;
33763372
let mut offsets = TryVec::with_capacity(offset_count.to_usize())?;
33773373
for _ in 0..offset_count {
33783374
offsets.push(be_u32(src)?.into())?;
@@ -3388,7 +3384,7 @@ fn read_stco<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
33883384
/// See ISOBMFF (ISO 14496-12:2015) § 8.7.5
33893385
fn read_co64<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
33903386
let (_, _) = read_fullbox_extra(src)?;
3391-
let offset_count = be_u32_with_limit(src)?;
3387+
let offset_count = be_u32(src)?;
33923388
let mut offsets = TryVec::with_capacity(offset_count.to_usize())?;
33933389
for _ in 0..offset_count {
33943390
offsets.push(be_u64(src)?)?;
@@ -3404,7 +3400,7 @@ fn read_co64<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
34043400
/// See ISOBMFF (ISO 14496-12:2015) § 8.6.2
34053401
fn read_stss<T: Read>(src: &mut BMFFBox<T>) -> Result<SyncSampleBox> {
34063402
let (_, _) = read_fullbox_extra(src)?;
3407-
let sample_count = be_u32_with_limit(src)?;
3403+
let sample_count = be_u32(src)?;
34083404
let mut samples = TryVec::with_capacity(sample_count.to_usize())?;
34093405
for _ in 0..sample_count {
34103406
samples.push(be_u32(src)?)?;
@@ -3420,11 +3416,11 @@ fn read_stss<T: Read>(src: &mut BMFFBox<T>) -> Result<SyncSampleBox> {
34203416
/// See ISOBMFF (ISO 14496-12:2015) § 8.7.4
34213417
fn read_stsc<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleToChunkBox> {
34223418
let (_, _) = read_fullbox_extra(src)?;
3423-
let sample_count = be_u32_with_limit(src)?;
3419+
let sample_count = be_u32(src)?;
34243420
let mut samples = TryVec::with_capacity(sample_count.to_usize())?;
34253421
for _ in 0..sample_count {
34263422
let first_chunk = be_u32(src)?;
3427-
let samples_per_chunk = be_u32_with_limit(src)?;
3423+
let samples_per_chunk = be_u32(src)?;
34283424
let sample_description_index = be_u32(src)?;
34293425
samples.push(SampleToChunk {
34303426
first_chunk,
@@ -3444,7 +3440,7 @@ fn read_stsc<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleToChunkBox> {
34443440
fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> {
34453441
let (version, _) = read_fullbox_extra(src)?;
34463442

3447-
let counts = be_u32_with_limit(src)?;
3443+
let counts = be_u32(src)?;
34483444

34493445
if src.bytes_left()
34503446
< counts
@@ -3462,7 +3458,7 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> {
34623458
// however, some buggy contents have negative value when version == 0.
34633459
// So we always use Version1 here.
34643460
0..=1 => {
3465-
let count = be_u32_with_limit(src)?;
3461+
let count = be_u32(src)?;
34663462
let offset = TimeOffsetVersion::Version1(be_i32(src)?);
34673463
(count, offset)
34683464
}
@@ -3486,7 +3482,7 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> {
34863482
fn read_stsz<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleSizeBox> {
34873483
let (_, _) = read_fullbox_extra(src)?;
34883484
let sample_size = be_u32(src)?;
3489-
let sample_count = be_u32_with_limit(src)?;
3485+
let sample_count = be_u32(src)?;
34903486
let mut sample_sizes = TryVec::new();
34913487
if sample_size == 0 {
34923488
sample_sizes.reserve(sample_count.to_usize())?;
@@ -3508,10 +3504,10 @@ fn read_stsz<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleSizeBox> {
35083504
/// See ISOBMFF (ISO 14496-12:2015) § 8.6.1.2
35093505
fn read_stts<T: Read>(src: &mut BMFFBox<T>) -> Result<TimeToSampleBox> {
35103506
let (_, _) = read_fullbox_extra(src)?;
3511-
let sample_count = be_u32_with_limit(src)?;
3507+
let sample_count = be_u32(src)?;
35123508
let mut samples = TryVec::with_capacity(sample_count.to_usize())?;
35133509
for _ in 0..sample_count {
3514-
let sample_count = be_u32_with_limit(src)?;
3510+
let sample_count = be_u32(src)?;
35153511
let sample_delta = be_u32(src)?;
35163512
samples.push(Sample {
35173513
sample_count,
@@ -4881,16 +4877,6 @@ fn be_u32<T: ReadBytesExt>(src: &mut T) -> Result<u32> {
48814877
src.read_u32::<byteorder::BigEndian>().map_err(From::from)
48824878
}
48834879

4884-
/// Using in reading table size and return error if it exceeds limitation.
4885-
fn be_u32_with_limit<T: ReadBytesExt>(src: &mut T) -> Result<u32> {
4886-
be_u32(src).and_then(|v| {
4887-
if v > TABLE_SIZE_LIMIT {
4888-
return Err(Error::OutOfMemory);
4889-
}
4890-
Ok(v)
4891-
})
4892-
}
4893-
48944880
fn be_u64<T: ReadBytesExt>(src: &mut T) -> Result<u64> {
48954881
src.read_u64::<byteorder::BigEndian>().map_err(From::from)
48964882
}

mp4parse/src/tests.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,23 +1218,6 @@ fn read_f4v_stsd() {
12181218
}
12191219
}
12201220

1221-
#[test]
1222-
fn max_table_limit() {
1223-
let elst = make_fullbox(BoxSize::Auto, b"elst", 1, |s| {
1224-
s.B32(super::TABLE_SIZE_LIMIT + 1)
1225-
})
1226-
.into_inner();
1227-
let mut stream = make_box(BoxSize::Auto, b"edts", |s| s.append_bytes(elst.as_slice()));
1228-
let mut iter = super::BoxIter::new(&mut stream);
1229-
let mut stream = iter.next_box().unwrap().unwrap();
1230-
let mut track = super::Track::new(0);
1231-
match super::read_edts(&mut stream, &mut track) {
1232-
Err(Error::OutOfMemory) => (),
1233-
Ok(_) => panic!("expected an error result"),
1234-
_ => panic!("expected a different error result"),
1235-
}
1236-
}
1237-
12381221
#[test]
12391222
fn unknown_video_sample_entry() {
12401223
let unknown_codec = make_box(BoxSize::Auto, b"yyyy", |s| s.append_repeated(0, 16)).into_inner();

mp4parse/src/unstable.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,8 @@ pub fn create_sample_table(
161161
// With large numbers of samples, the cost of many allocations dominates,
162162
// so it's worth iterating twice to allocate sample_table just once.
163163
let total_sample_count = sample_to_chunk_iter(&stsc.samples, &stco.offsets)
164-
.by_ref()
165164
.map(|(_, sample_counts)| sample_counts.to_usize())
166-
.sum();
165+
.try_fold(0usize, usize::checked_add)?;
167166
let mut sample_table = TryVec::with_capacity(total_sample_count).ok()?;
168167

169168
for i in sample_to_chunk_iter(&stsc.samples, &stco.offsets) {
@@ -226,7 +225,7 @@ pub fn create_sample_table(
226225
};
227226

228227
// sum_delta is the sum of stts_iter delta.
229-
// According to sepc:
228+
// According to spec:
230229
// decode time => DT(n) = DT(n-1) + STTS(n)
231230
// composition time => CT(n) = DT(n) + CTTS(n)
232231
// Note:

0 commit comments

Comments
 (0)