Skip to content

Commit 276e314

Browse files
Pawin Vongmasaandi34
authored andcommitted
Impose a size bound for dynamically allocated tables in stbl.
Impose a restriction of 200MiB for tables in stsc, stts, ctts and stss boxes. Also change mTimeToSample from Vector to array. Bug: 29367429 Change-Id: I953bea9fe0590268cf27376740f582dc88563d42 (cherry picked from commit 583a012)
1 parent 013273d commit 276e314

File tree

2 files changed

+141
-24
lines changed

2 files changed

+141
-24
lines changed

media/libstagefright/SampleTable.cpp

Lines changed: 134 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ SampleTable::SampleTable(const sp<DataSource> &source)
123123
mNumSampleSizes(0),
124124
mHasTimeToSample(false),
125125
mTimeToSampleCount(0),
126-
mTimeToSample(),
126+
mTimeToSample(NULL),
127127
mSampleTimeEntries(NULL),
128128
mCompositionTimeDeltaEntries(NULL),
129129
mNumCompositionTimeDeltaEntries(0),
@@ -132,7 +132,8 @@ SampleTable::SampleTable(const sp<DataSource> &source)
132132
mNumSyncSamples(0),
133133
mSyncSamples(NULL),
134134
mLastSyncSampleIndex(0),
135-
mSampleToChunkEntries(NULL) {
135+
mSampleToChunkEntries(NULL),
136+
mTotalSize(0) {
136137
mSampleIterator = new SampleIterator(this);
137138
}
138139

@@ -143,6 +144,9 @@ SampleTable::~SampleTable() {
143144
delete[] mSyncSamples;
144145
mSyncSamples = NULL;
145146

147+
delete[] mTimeToSample;
148+
mTimeToSample = NULL;
149+
146150
delete mCompositionDeltaLookup;
147151
mCompositionDeltaLookup = NULL;
148152

@@ -233,11 +237,43 @@ status_t SampleTable::setSampleToChunkParams(
233237
return ERROR_MALFORMED;
234238
}
235239

236-
if (SIZE_MAX / sizeof(SampleToChunkEntry) <= mNumSampleToChunkOffsets)
240+
if ((uint64_t)SIZE_MAX / sizeof(SampleToChunkEntry) <=
241+
(uint64_t)mNumSampleToChunkOffsets) {
242+
ALOGE("Sample-to-chunk table size too large.");
237243
return ERROR_OUT_OF_RANGE;
244+
}
245+
246+
mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
247+
sizeof(SampleToChunkEntry);
248+
if (mTotalSize > kMaxTotalSize) {
249+
ALOGE("Sample-to-chunk table size would make sample table too large.\n"
250+
" Requested sample-to-chunk table size = %llu\n"
251+
" Eventual sample table size >= %llu\n"
252+
" Allowed sample table size = %llu\n",
253+
(unsigned long long)mNumSampleToChunkOffsets *
254+
sizeof(SampleToChunkEntry),
255+
(unsigned long long)mTotalSize,
256+
(unsigned long long)kMaxTotalSize);
257+
return ERROR_OUT_OF_RANGE;
258+
}
238259

239260
mSampleToChunkEntries =
240-
new SampleToChunkEntry[mNumSampleToChunkOffsets];
261+
new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
262+
if (!mSampleToChunkEntries) {
263+
ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
264+
(unsigned long long)mNumSampleToChunkOffsets);
265+
return ERROR_OUT_OF_RANGE;
266+
}
267+
268+
if (mNumSampleToChunkOffsets == 0) {
269+
return OK;
270+
}
271+
272+
if ((off64_t)(SIZE_MAX - 8 -
273+
((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
274+
< mSampleToChunkOffset) {
275+
return ERROR_MALFORMED;
276+
}
241277

242278
for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
243279
uint8_t buffer[12];
@@ -246,8 +282,11 @@ status_t SampleTable::setSampleToChunkParams(
246282
!= (ssize_t)sizeof(buffer)) {
247283
return ERROR_IO;
248284
}
249-
250-
CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec.
285+
// chunk index is 1 based in the spec.
286+
if (U32_AT(buffer) < 1) {
287+
ALOGE("b/23534160");
288+
return ERROR_OUT_OF_RANGE;
289+
}
251290

252291
// We want the chunk index to be 0-based.
253292
mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
@@ -347,20 +386,41 @@ status_t SampleTable::setTimeToSampleParams(
347386
// 2) mTimeToSampleCount is the number of entries of the time-to-sample
348387
// table.
349388
// 3) We hope that the table size does not exceed UINT32_MAX.
350-
ALOGE(" Error: Time-to-sample table size too large.");
389+
ALOGE("Time-to-sample table size too large.");
351390
return ERROR_OUT_OF_RANGE;
352391
}
353392

354393
// Note: At this point, we know that mTimeToSampleCount * 2 will not
355394
// overflow because of the above condition.
356-
if (!mDataSource->getVector(data_offset + 8, &mTimeToSample,
357-
mTimeToSampleCount * 2)) {
358-
ALOGE(" Error: Incomplete data read for time-to-sample table.");
395+
396+
uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
397+
mTotalSize += allocSize;
398+
if (mTotalSize > kMaxTotalSize) {
399+
ALOGE("Time-to-sample table size would make sample table too large.\n"
400+
" Requested time-to-sample table size = %llu\n"
401+
" Eventual sample table size >= %llu\n"
402+
" Allowed sample table size = %llu\n",
403+
(unsigned long long)allocSize,
404+
(unsigned long long)mTotalSize,
405+
(unsigned long long)kMaxTotalSize);
406+
return ERROR_OUT_OF_RANGE;
407+
}
408+
409+
mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
410+
if (!mTimeToSample) {
411+
ALOGE("Cannot allocate time-to-sample table with %llu entries.",
412+
(unsigned long long)mTimeToSampleCount);
413+
return ERROR_OUT_OF_RANGE;
414+
}
415+
416+
if (mDataSource->readAt(data_offset + 8, mTimeToSample,
417+
(size_t)allocSize) < (ssize_t)allocSize) {
418+
ALOGE("Incomplete data read for time-to-sample table.");
359419
return ERROR_IO;
360420
}
361421

362-
for (size_t i = 0; i < mTimeToSample.size(); ++i) {
363-
mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]);
422+
for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
423+
mTimeToSample[i] = ntohl(mTimeToSample[i]);
364424
}
365425

366426
mHasTimeToSample = true;
@@ -396,14 +456,31 @@ status_t SampleTable::setCompositionTimeToSampleParams(
396456
mNumCompositionTimeDeltaEntries = numEntries;
397457
uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t);
398458
if (allocSize > SIZE_MAX) {
459+
ALOGE("Composition-time-to-sample table size too large.");
460+
return ERROR_OUT_OF_RANGE;
461+
}
462+
463+
mTotalSize += allocSize;
464+
if (mTotalSize > kMaxTotalSize) {
465+
ALOGE("Composition-time-to-sample table would make sample table too large.\n"
466+
" Requested composition-time-to-sample table size = %llu\n"
467+
" Eventual sample table size >= %llu\n"
468+
" Allowed sample table size = %llu\n",
469+
(unsigned long long)allocSize,
470+
(unsigned long long)mTotalSize,
471+
(unsigned long long)kMaxTotalSize);
399472
return ERROR_OUT_OF_RANGE;
400473
}
401474

402-
mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
475+
mCompositionTimeDeltaEntries = new (std::nothrow) uint32_t[2 * numEntries];
476+
if (!mCompositionTimeDeltaEntries) {
477+
ALOGE("Cannot allocate composition-time-to-sample table with %llu "
478+
"entries.", (unsigned long long)numEntries);
479+
return ERROR_OUT_OF_RANGE;
480+
}
403481

404-
if (mDataSource->readAt(
405-
data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
406-
< (ssize_t)numEntries * 8) {
482+
if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
483+
(size_t)allocSize) < (ssize_t)allocSize) {
407484
delete[] mCompositionTimeDeltaEntries;
408485
mCompositionTimeDeltaEntries = NULL;
409486

@@ -444,15 +521,33 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size)
444521
ALOGV("Table of sync samples is empty or has only a single entry!");
445522
}
446523

447-
uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t);
524+
uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
448525
if (allocSize > SIZE_MAX) {
526+
ALOGE("Sync sample table size too large.");
527+
return ERROR_OUT_OF_RANGE;
528+
}
529+
530+
mTotalSize += allocSize;
531+
if (mTotalSize > kMaxTotalSize) {
532+
ALOGE("Sync sample table size would make sample table too large.\n"
533+
" Requested sync sample table size = %llu\n"
534+
" Eventual sample table size >= %llu\n"
535+
" Allowed sample table size = %llu\n",
536+
(unsigned long long)allocSize,
537+
(unsigned long long)mTotalSize,
538+
(unsigned long long)kMaxTotalSize);
539+
return ERROR_OUT_OF_RANGE;
540+
}
541+
542+
mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
543+
if (!mSyncSamples) {
544+
ALOGE("Cannot allocate sync sample table with %llu entries.",
545+
(unsigned long long)mNumSyncSamples);
449546
return ERROR_OUT_OF_RANGE;
450547
}
451548

452-
mSyncSamples = new uint32_t[mNumSyncSamples];
453-
size_t size = mNumSyncSamples * sizeof(uint32_t);
454-
if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
455-
!= (ssize_t)size) {
549+
if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples,
550+
(size_t)allocSize) != (ssize_t)allocSize) {
456551
return ERROR_IO;
457552
}
458553

@@ -517,7 +612,24 @@ void SampleTable::buildSampleEntriesTable() {
517612
return;
518613
}
519614

520-
mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];
615+
mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
616+
if (mTotalSize > kMaxTotalSize) {
617+
ALOGE("Sample entry table size would make sample table too large.\n"
618+
" Requested sample entry table size = %llu\n"
619+
" Eventual sample table size >= %llu\n"
620+
" Allowed sample table size = %llu\n",
621+
(unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
622+
(unsigned long long)mTotalSize,
623+
(unsigned long long)kMaxTotalSize);
624+
return;
625+
}
626+
627+
mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
628+
if (!mSampleTimeEntries) {
629+
ALOGE("Cannot allocate sample entry table with %llu entries.",
630+
(unsigned long long)mNumSampleSizes);
631+
return;
632+
}
521633

522634
uint32_t sampleIndex = 0;
523635
uint32_t sampleTime = 0;

media/libstagefright/include/SampleTable.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include <media/stagefright/MediaErrors.h>
2525
#include <utils/RefBase.h>
2626
#include <utils/threads.h>
27-
#include <utils/Vector.h>
2827

2928
namespace android {
3029

@@ -94,6 +93,9 @@ class SampleTable : public RefBase {
9493
static const uint32_t kSampleSizeType32;
9594
static const uint32_t kSampleSizeTypeCompact;
9695

96+
// Limit the total size of all internal tables to 200MiB.
97+
static const size_t kMaxTotalSize = 200 * (1 << 20);
98+
9799
sp<DataSource> mDataSource;
98100
Mutex mLock;
99101

@@ -111,7 +113,7 @@ class SampleTable : public RefBase {
111113

112114
bool mHasTimeToSample;
113115
uint32_t mTimeToSampleCount;
114-
Vector<uint32_t> mTimeToSample;
116+
uint32_t* mTimeToSample;
115117

116118
struct SampleTimeEntry {
117119
uint32_t mSampleIndex;
@@ -137,6 +139,9 @@ class SampleTable : public RefBase {
137139
};
138140
SampleToChunkEntry *mSampleToChunkEntries;
139141

142+
// Approximate size of all tables combined.
143+
uint64_t mTotalSize;
144+
140145
friend struct SampleIterator;
141146

142147
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);

0 commit comments

Comments
 (0)