diff options
author | Marco Nelissen <marcone@google.com> | 2014-06-05 10:37:26 -0700 |
---|---|---|
committer | Marco Nelissen <marcone@google.com> | 2014-06-06 11:25:26 -0700 |
commit | a91b538853e94191fbceab5f5050940dd6b96577 (patch) | |
tree | 306517c19632c8a054e6c7f60d495a3172e909e1 | |
parent | a78df9591c698834f3d57f6e882e4b0af5f8f473 (diff) | |
download | frameworks_av-a91b538853e94191fbceab5f5050940dd6b96577.zip frameworks_av-a91b538853e94191fbceab5f5050940dd6b96577.tar.gz frameworks_av-a91b538853e94191fbceab5f5050940dd6b96577.tar.bz2 |
Guard against malformed files
b/15433074
Change-Id: I35363def42d38eba49dd5aece566fd345743937e
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 05caf75..2e39036 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -478,11 +478,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; @@ -505,8 +514,6 @@ status_t MPEG4Extractor::readMetaData() { } else { mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); } - - mInitCheck = OK; } else { mInitCheck = err; } @@ -758,8 +765,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; } |