summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Jia <wjia@google.com>2017-02-14 17:07:24 -0800
committerAndreas Blaesius <skate4life@gmx.de>2017-09-17 22:11:10 +0200
commit42b62872275ff757b999cf189fe48693c576a282 (patch)
tree15b108c5ad46346534b9a5ecd99a6502db72c0bf
parentc00501184d8566a17e3a26a76028bce26f59cf76 (diff)
downloadframeworks_av-42b62872275ff757b999cf189fe48693c576a282.tar.gz
frameworks_av-42b62872275ff757b999cf189fe48693c576a282.tar.bz2
frameworks_av-42b62872275ff757b999cf189fe48693c576a282.zip
MPEG4Extractor: ensure returned status is checked.
Also fix handling of zero atom size in MPEG4Source::parseChunk. IDataSource: ensure readAt returns correct status. Test: manually test with mediaplayer. Bug: 34718515 Change-Id: I1219ec579aa0876dc1230e36af46b158b84c6d77 (cherry picked from commit ff1fb4d5cdd3b2b28c69edd8cd3021e335ca381a) (cherry picked from commit 371561214467f848496928914f771703d6c331e6) Change-Id: I51546975ac0992cff7cf890a71a177e1058ed613 CVE-2017-0774
-rw-r--r--media/libmedia/IDataSource.cpp12
-rwxr-xr-xmedia/libstagefright/MPEG4Extractor.cpp67
2 files changed, 69 insertions, 10 deletions
diff --git a/media/libmedia/IDataSource.cpp b/media/libmedia/IDataSource.cpp
index 76d1d68ef8..a969c7db6e 100644
--- a/media/libmedia/IDataSource.cpp
+++ b/media/libmedia/IDataSource.cpp
@@ -50,8 +50,16 @@ struct BpDataSource : public BpInterface<IDataSource> {
data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
data.writeInt64(offset);
data.writeInt64(size);
- remote()->transact(READ_AT, data, &reply);
- return reply.readInt64();
+ status_t err = remote()->transact(READ_AT, data, &reply);
+ if (err != OK) {
+ return err;
+ }
+ int64_t value = 0;
+ err = reply.readInt64(&value);
+ if (err != OK) {
+ return err;
+ }
+ return (ssize_t)value;
}
virtual status_t getSize(off64_t* size) {
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5d97181034..8c66c29d91 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -67,6 +67,7 @@ public:
Vector<SidxEntry> &sidx,
const Trex *trex,
off64_t firstMoofOffset);
+ virtual status_t init();
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
@@ -2046,7 +2047,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
*offset += chunk_size;
if (underQTMetaPath(mPath, 3)) {
- parseQTMetaKey(data_offset, chunk_data_size);
+ status_t err = parseQTMetaKey(data_offset, chunk_data_size);
+ if (err != OK) {
+ return err;
+ }
}
break;
}
@@ -2190,7 +2194,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
case FOURCC('s', 'i', 'd', 'x'):
{
- parseSegmentIndex(data_offset, chunk_data_size);
+ status_t err = parseSegmentIndex(data_offset, chunk_data_size);
+ if (err != OK) {
+ return err;
+ }
*offset += chunk_size;
return UNKNOWN_ERROR; // stop parsing after sidx
}
@@ -2200,7 +2207,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
// check if we're parsing 'ilst' for meta keys
// if so, treat type as a number (key-id).
if (underQTMetaPath(mPath, 3)) {
- parseQTMetaVal(chunk_type, data_offset, chunk_data_size);
+ status_t err = parseQTMetaVal(chunk_type, data_offset, chunk_data_size);
+ if (err != OK) {
+ return err;
+ }
}
*offset += chunk_size;
@@ -2940,9 +2950,13 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
ALOGV("getTrack called, pssh: %zu", mPssh.size());
- return new MPEG4Source(this,
+ sp<MPEG4Source> source = new MPEG4Source(this,
track->meta, mDataSource, track->timescale, track->sampleTable,
mSidxEntries, trex, mMoofOffset);
+ if (source->init() != OK) {
+ return NULL;
+ }
+ return source;
}
// static
@@ -3339,6 +3353,7 @@ MPEG4Source::MPEG4Source(
mTrex(trex),
mFirstMoofOffset(firstMoofOffset),
mCurrentMoofOffset(firstMoofOffset),
+ mNextMoofOffset(-1),
mCurrentTime(0),
mCurrentSampleInfoAllocSize(0),
mCurrentSampleInfoSizes(NULL),
@@ -3405,10 +3420,14 @@ MPEG4Source::MPEG4Source(
CHECK(format->findInt32(kKeyTrackID, &mTrackId));
+}
+
+status_t MPEG4Source::init() {
if (mFirstMoofOffset != 0) {
off64_t offset = mFirstMoofOffset;
- parseChunk(&offset);
+ return parseChunk(&offset);
}
+ return OK;
}
MPEG4Source::~MPEG4Source() {
@@ -3532,9 +3551,30 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
}
chunk_size = ntohl(hdr[0]);
chunk_type = ntohl(hdr[1]);
+ if (chunk_size == 1) {
+ // ISO/IEC 14496-12:2012, 8.8.4 Movie Fragment Box, moof is a Box
+ // which is defined in 4.2 Object Structure.
+ // When chunk_size==1, 8 bytes follows as "largesize".
+ if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
+ return ERROR_IO;
+ }
+ chunk_size = ntoh64(chunk_size);
+ if (chunk_size < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return ERROR_MALFORMED;
+ }
+ } else if (chunk_size == 0) {
+ // next box extends to end of file.
+ } else if (chunk_size < 8) {
+ // The smallest valid chunk is 8 bytes long in this case.
+ return ERROR_MALFORMED;
+ }
+
if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
mNextMoofOffset = *offset;
break;
+ } else if (chunk_size == 0) {
+ break;
}
*offset += chunk_size;
}
@@ -4399,17 +4439,25 @@ status_t MPEG4Source::fragmentedRead(
totalOffset += se->mSize;
}
mCurrentMoofOffset = totalOffset;
+ mNextMoofOffset = -1;
mCurrentSamples.clear();
mCurrentSampleIndex = 0;
- parseChunk(&totalOffset);
+ status_t err = parseChunk(&totalOffset);
+ if (err != OK) {
+ return err;
+ }
mCurrentTime = totalTime * mTimescale / 1000000ll;
} else {
// without sidx boxes, we can only seek to 0
mCurrentMoofOffset = mFirstMoofOffset;
+ mNextMoofOffset = -1;
mCurrentSamples.clear();
mCurrentSampleIndex = 0;
off64_t tmp = mCurrentMoofOffset;
- parseChunk(&tmp);
+ status_t err = parseChunk(&tmp);
+ if (err != OK) {
+ return err;
+ }
mCurrentTime = 0;
}
@@ -4438,7 +4486,10 @@ status_t MPEG4Source::fragmentedRead(
mCurrentMoofOffset = nextMoof;
mCurrentSamples.clear();
mCurrentSampleIndex = 0;
- parseChunk(&nextMoof);
+ status_t err = parseChunk(&nextMoof);
+ if (err != OK) {
+ return err;
+ }
if (mCurrentSampleIndex >= mCurrentSamples.size()) {
return ERROR_END_OF_STREAM;
}