Loading include/media/stagefright/DataSource.h +7 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <utils/RefBase.h> #include <utils/threads.h> #include <drm/DrmManagerClient.h> #include <vector> namespace android { Loading Loading @@ -77,7 +78,7 @@ public: // The default value for chunkSize is set to read at least 4k bytes at a // time, depending on sizeof(T). template <typename T> bool getVector(off64_t offset, Vector<T>* x, size_t count, bool getVector(off64_t offset, std::vector<T>* x, size_t count, size_t chunkSize = (4095 / sizeof(T)) + 1); // May return ERROR_UNSUPPORTED. Loading Loading @@ -131,7 +132,7 @@ private: }; template <typename T> bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, bool DataSource::getVector(off64_t offset, std::vector<T>* x, size_t count, size_t chunkSize) { x->clear(); Loading @@ -157,10 +158,11 @@ bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, if (numBytesRead < numBytesPerChunk) { // This case is triggered when the stream ends before the whole // chunk is read. x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); x->insert(x->end(), &tmp[0], &tmp[(size_t)numBytesRead / sizeof(T)]); return false; } x->appendArray(tmp, chunkSize); x->insert(x->end(), &tmp[0], &tmp[chunkSize]); offset += numBytesPerChunk; } Loading @@ -171,7 +173,7 @@ bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, if (numBytesRead == -1) { return false; } x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); x->insert(x->end(), &tmp[0], &tmp[(size_t)numBytesRead / sizeof(T)]); return x->size() == count; } Loading media/libstagefright/SampleTable.cpp +89 −12 Original line number Diff line number Diff line Loading @@ -132,7 +132,8 @@ SampleTable::SampleTable(const sp<DataSource> &source) mNumSyncSamples(0), mSyncSamples(NULL), mLastSyncSampleIndex(0), mSampleToChunkEntries(NULL) { mSampleToChunkEntries(NULL), mTotalSize(0) { mSampleIterator = new SampleIterator(this); } Loading Loading @@ -234,11 +235,33 @@ status_t SampleTable::setSampleToChunkParams( } if (SIZE_MAX / sizeof(SampleToChunkEntry) <= mNumSampleToChunkOffsets) ALOGE("Sample-to-chunk table size too large."); return ERROR_OUT_OF_RANGE; } mTotalSize += (size_t)mNumSampleToChunkOffsets * sizeof(SampleToChunkEntry); if (mTotalSize > kMaxTotalSize) { ALOGE("Sample-to-chunk table size would make sample table too large.\n" " Requested sample-to-chunk table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)mNumSampleToChunkOffsets * sizeof(SampleToChunkEntry), (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } mSampleToChunkEntries = new SampleToChunkEntry[mNumSampleToChunkOffsets]; if ((off64_t)(SIZE_MAX - 8 - ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry))) < mSampleToChunkOffset) { return ERROR_MALFORMED; } for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { uint8_t buffer[12]; if (mDataSource->readAt( Loading Loading @@ -348,20 +371,33 @@ status_t SampleTable::setTimeToSampleParams( // 2) mTimeToSampleCount is the number of entries of the time-to-sample // table. // 3) We hope that the table size does not exceed UINT32_MAX. ALOGE(" Error: Time-to-sample table size too large."); ALOGE("Time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } // Note: At this point, we know that mTimeToSampleCount * 2 will not // overflow because of the above condition. mTotalSize += (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); if (mTotalSize > kMaxTotalSize) { ALOGE("Time-to-sample table size would make sample table too large.\n" " Requested time-to-sample table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)mTimeToSampleCount * 2 * sizeof(uint32_t), (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } if (!mDataSource->getVector(data_offset + 8, &mTimeToSample, mTimeToSampleCount * 2)) { ALOGE(" Error: Incomplete data read for time-to-sample table."); ALOGE("Incomplete data read for time-to-sample table."); return ERROR_IO; } for (size_t i = 0; i < mTimeToSample.size(); ++i) { mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]); mTimeToSample[i] = ntohl(mTimeToSample[i]); } mHasTimeToSample = true; Loading Loading @@ -397,14 +433,26 @@ status_t SampleTable::setCompositionTimeToSampleParams( mNumCompositionTimeDeltaEntries = numEntries; uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t); if (allocSize > SIZE_MAX) { ALOGE("Composition-time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } mTotalSize += allocSize; if (mTotalSize > kMaxTotalSize) { ALOGE("Composition-time-to-sample table would make sample table too large.\n" " Requested composition-time-to-sample table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)allocSize, (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries]; if (mDataSource->readAt( data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8) < (ssize_t)numEntries * 8) { if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries, (size_t)allocSize) < (ssize_t)allocSize) { delete[] mCompositionTimeDeltaEntries; mCompositionTimeDeltaEntries = NULL; Loading Loading @@ -447,13 +495,28 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t); if (allocSize > SIZE_MAX) { ALOGE("Sync sample table size too large."); return ERROR_OUT_OF_RANGE; } mTotalSize += allocSize; if (mTotalSize > kMaxTotalSize) { ALOGE("Sync sample table size would make sample table too large.\n" " Requested sync sample table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)allocSize, (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } mSyncSamples = new uint32_t[mNumSyncSamples]; size_t size = mNumSyncSamples * sizeof(uint32_t); if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size) != (ssize_t)size) { mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples]; if (!mSyncSamples) return ERROR_OUT_OF_RANGE; if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, (size_t)allocSize) != (ssize_t)allocSize) { return ERROR_IO; } Loading Loading @@ -521,7 +584,21 @@ void SampleTable::buildSampleEntriesTable() { return; } mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes]; mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry); if (mTotalSize > kMaxTotalSize) { ALOGE("Sample entry table size would make sample table too large.\n" " Requested sample entry table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry), (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return; } mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes]; if (!mSampleTimeEntries) return; uint32_t sampleIndex = 0; uint32_t sampleTime = 0; Loading media/libstagefright/include/SampleTable.h +8 −2 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ #include <media/stagefright/MediaErrors.h> #include <utils/RefBase.h> #include <utils/threads.h> #include <utils/Vector.h> #include <vector> namespace android { Loading Loading @@ -96,6 +96,9 @@ private: static const uint32_t kSampleSizeType32; static const uint32_t kSampleSizeTypeCompact; // Limit the total size of all internal tables to 200MiB. static const size_t kMaxTotalSize = 200 * (1 << 20); sp<DataSource> mDataSource; Mutex mLock; Loading @@ -113,7 +116,7 @@ private: bool mHasTimeToSample; uint32_t mTimeToSampleCount; Vector<uint32_t> mTimeToSample; std::vector<uint32_t> mTimeToSample; struct SampleTimeEntry { uint32_t mSampleIndex; Loading @@ -139,6 +142,9 @@ private: }; SampleToChunkEntry *mSampleToChunkEntries; // Approximate size of all tables combined. uint64_t mTotalSize; friend struct SampleIterator; // normally we don't round Loading Loading
include/media/stagefright/DataSource.h +7 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <utils/RefBase.h> #include <utils/threads.h> #include <drm/DrmManagerClient.h> #include <vector> namespace android { Loading Loading @@ -77,7 +78,7 @@ public: // The default value for chunkSize is set to read at least 4k bytes at a // time, depending on sizeof(T). template <typename T> bool getVector(off64_t offset, Vector<T>* x, size_t count, bool getVector(off64_t offset, std::vector<T>* x, size_t count, size_t chunkSize = (4095 / sizeof(T)) + 1); // May return ERROR_UNSUPPORTED. Loading Loading @@ -131,7 +132,7 @@ private: }; template <typename T> bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, bool DataSource::getVector(off64_t offset, std::vector<T>* x, size_t count, size_t chunkSize) { x->clear(); Loading @@ -157,10 +158,11 @@ bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, if (numBytesRead < numBytesPerChunk) { // This case is triggered when the stream ends before the whole // chunk is read. x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); x->insert(x->end(), &tmp[0], &tmp[(size_t)numBytesRead / sizeof(T)]); return false; } x->appendArray(tmp, chunkSize); x->insert(x->end(), &tmp[0], &tmp[chunkSize]); offset += numBytesPerChunk; } Loading @@ -171,7 +173,7 @@ bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, if (numBytesRead == -1) { return false; } x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); x->insert(x->end(), &tmp[0], &tmp[(size_t)numBytesRead / sizeof(T)]); return x->size() == count; } Loading
media/libstagefright/SampleTable.cpp +89 −12 Original line number Diff line number Diff line Loading @@ -132,7 +132,8 @@ SampleTable::SampleTable(const sp<DataSource> &source) mNumSyncSamples(0), mSyncSamples(NULL), mLastSyncSampleIndex(0), mSampleToChunkEntries(NULL) { mSampleToChunkEntries(NULL), mTotalSize(0) { mSampleIterator = new SampleIterator(this); } Loading Loading @@ -234,11 +235,33 @@ status_t SampleTable::setSampleToChunkParams( } if (SIZE_MAX / sizeof(SampleToChunkEntry) <= mNumSampleToChunkOffsets) ALOGE("Sample-to-chunk table size too large."); return ERROR_OUT_OF_RANGE; } mTotalSize += (size_t)mNumSampleToChunkOffsets * sizeof(SampleToChunkEntry); if (mTotalSize > kMaxTotalSize) { ALOGE("Sample-to-chunk table size would make sample table too large.\n" " Requested sample-to-chunk table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)mNumSampleToChunkOffsets * sizeof(SampleToChunkEntry), (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } mSampleToChunkEntries = new SampleToChunkEntry[mNumSampleToChunkOffsets]; if ((off64_t)(SIZE_MAX - 8 - ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry))) < mSampleToChunkOffset) { return ERROR_MALFORMED; } for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { uint8_t buffer[12]; if (mDataSource->readAt( Loading Loading @@ -348,20 +371,33 @@ status_t SampleTable::setTimeToSampleParams( // 2) mTimeToSampleCount is the number of entries of the time-to-sample // table. // 3) We hope that the table size does not exceed UINT32_MAX. ALOGE(" Error: Time-to-sample table size too large."); ALOGE("Time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } // Note: At this point, we know that mTimeToSampleCount * 2 will not // overflow because of the above condition. mTotalSize += (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); if (mTotalSize > kMaxTotalSize) { ALOGE("Time-to-sample table size would make sample table too large.\n" " Requested time-to-sample table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)mTimeToSampleCount * 2 * sizeof(uint32_t), (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } if (!mDataSource->getVector(data_offset + 8, &mTimeToSample, mTimeToSampleCount * 2)) { ALOGE(" Error: Incomplete data read for time-to-sample table."); ALOGE("Incomplete data read for time-to-sample table."); return ERROR_IO; } for (size_t i = 0; i < mTimeToSample.size(); ++i) { mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]); mTimeToSample[i] = ntohl(mTimeToSample[i]); } mHasTimeToSample = true; Loading Loading @@ -397,14 +433,26 @@ status_t SampleTable::setCompositionTimeToSampleParams( mNumCompositionTimeDeltaEntries = numEntries; uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t); if (allocSize > SIZE_MAX) { ALOGE("Composition-time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } mTotalSize += allocSize; if (mTotalSize > kMaxTotalSize) { ALOGE("Composition-time-to-sample table would make sample table too large.\n" " Requested composition-time-to-sample table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)allocSize, (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries]; if (mDataSource->readAt( data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8) < (ssize_t)numEntries * 8) { if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries, (size_t)allocSize) < (ssize_t)allocSize) { delete[] mCompositionTimeDeltaEntries; mCompositionTimeDeltaEntries = NULL; Loading Loading @@ -447,13 +495,28 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t); if (allocSize > SIZE_MAX) { ALOGE("Sync sample table size too large."); return ERROR_OUT_OF_RANGE; } mTotalSize += allocSize; if (mTotalSize > kMaxTotalSize) { ALOGE("Sync sample table size would make sample table too large.\n" " Requested sync sample table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)allocSize, (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return ERROR_OUT_OF_RANGE; } mSyncSamples = new uint32_t[mNumSyncSamples]; size_t size = mNumSyncSamples * sizeof(uint32_t); if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size) != (ssize_t)size) { mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples]; if (!mSyncSamples) return ERROR_OUT_OF_RANGE; if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, (size_t)allocSize) != (ssize_t)allocSize) { return ERROR_IO; } Loading Loading @@ -521,7 +584,21 @@ void SampleTable::buildSampleEntriesTable() { return; } mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes]; mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry); if (mTotalSize > kMaxTotalSize) { ALOGE("Sample entry table size would make sample table too large.\n" " Requested sample entry table size = %llu\n" " Eventual sample table size >= %llu\n" " Allowed sample table size = %llu\n", (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry), (unsigned long long)mTotalSize, (unsigned long long)kMaxTotalSize); return; } mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes]; if (!mSampleTimeEntries) return; uint32_t sampleIndex = 0; uint32_t sampleTime = 0; Loading
media/libstagefright/include/SampleTable.h +8 −2 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ #include <media/stagefright/MediaErrors.h> #include <utils/RefBase.h> #include <utils/threads.h> #include <utils/Vector.h> #include <vector> namespace android { Loading Loading @@ -96,6 +96,9 @@ private: static const uint32_t kSampleSizeType32; static const uint32_t kSampleSizeTypeCompact; // Limit the total size of all internal tables to 200MiB. static const size_t kMaxTotalSize = 200 * (1 << 20); sp<DataSource> mDataSource; Mutex mLock; Loading @@ -113,7 +116,7 @@ private: bool mHasTimeToSample; uint32_t mTimeToSampleCount; Vector<uint32_t> mTimeToSample; std::vector<uint32_t> mTimeToSample; struct SampleTimeEntry { uint32_t mSampleIndex; Loading @@ -139,6 +142,9 @@ private: }; SampleToChunkEntry *mSampleToChunkEntries; // Approximate size of all tables combined. uint64_t mTotalSize; friend struct SampleIterator; // normally we don't round Loading