summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorMarco Nelissen <marcone@google.com>2014-06-05 10:37:26 -0700
committerMarco Nelissen <marcone@google.com>2014-06-10 14:29:47 -0700
commitd7e8d9a7393b5429f8f13a6794b9b04d37390fb5 (patch)
treedffa37b5c27ada5046450ce6aa91e23e171e7525 /media
parentd8754e07e23eecb68068c0c392aeb0428c529e4e (diff)
downloadframeworks_av-d7e8d9a7393b5429f8f13a6794b9b04d37390fb5.zip
frameworks_av-d7e8d9a7393b5429f8f13a6794b9b04d37390fb5.tar.gz
frameworks_av-d7e8d9a7393b5429f8f13a6794b9b04d37390fb5.tar.bz2
Guard against malformed files
b/15433074 Change-Id: I35363def42d38eba49dd5aece566fd345743937e
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp32
1 files changed, 28 insertions, 4 deletions
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 76546f3..aabe0ec 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -482,11 +482,20 @@ status_t MPEG4Extractor::readMetaData() {
off64_t offset = 0;
status_t err;
while (true) {
+ off64_t orig_offset = offset;
err = parseChunk(&offset, 0);
- if (err == OK) {
+
+ if (offset <= orig_offset) {
+ // only continue parsing if the offset was advanced,
+ // otherwise we might end up in an infinite loop
+ ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset);
+ err = ERROR_MALFORMED;
+ break;
+ } else if (err == OK) {
continue;
+ } else if (err != UNKNOWN_ERROR) {
+ break;
}
-
uint32_t hdr[2];
if (mDataSource->readAt(offset, hdr, 8) < 8) {
break;
@@ -509,8 +518,6 @@ status_t MPEG4Extractor::readMetaData() {
} else {
mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
}
-
- mInitCheck = OK;
} else {
mInitCheck = err;
}
@@ -762,8 +769,25 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
// The smallest valid chunk is 16 bytes long in this case.
return ERROR_MALFORMED;
}
+ } else if (chunk_size == 0) {
+ if (depth == 0) {
+ // atom extends to end of file
+ off64_t sourceSize;
+ if (mDataSource->getSize(&sourceSize) == OK) {
+ chunk_size = (sourceSize - *offset);
+ } else {
+ // XXX could we just pick a "sufficiently large" value here?
+ ALOGE("atom size is 0, and data source has no size");
+ return ERROR_MALFORMED;
+ }
+ } else {
+ // not allowed for non-toplevel atoms, skip it
+ *offset += 4;
+ return OK;
+ }
} else if (chunk_size < 8) {
// The smallest valid chunk is 8 bytes long.
+ ALOGE("invalid chunk size: %d", int(chunk_size));
return ERROR_MALFORMED;
}