diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp index 883e3ae4060..d6c88bd12dc 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp @@ -855,6 +855,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { } } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->sampleTable = new SampleTable(mDataSource); } @@ -980,6 +983,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { break; } else if (media_time == -1) { // Starting offsets for tracks (streams) are represented by an initial empty edit. + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->empty_duration = segment_duration; continue; } else if (i > 1) { @@ -987,6 +993,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { ALOGW("multiple edit list entries, A/V sync will be wrong"); break; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->segment_duration = segment_duration; mLastTrack->media_time = media_time; } @@ -1003,6 +1012,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { } original_fourcc = ntohl(original_fourcc); ALOGV("read original format: %d", original_fourcc); + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc)); uint32_t num_channels = 0; uint32_t sample_rate = 0; @@ -1067,6 +1079,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId); mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize); mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16); @@ -1156,6 +1171,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->timescale = ntohl(timescale); // Now that we've parsed the media timescale, we can interpret @@ -1248,6 +1266,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // display the timed text. // For encrypted files, there may also be more than one entry. const char *mime; + if (!mLastTrack) { + return ERROR_MALFORMED; + } CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) && strcasecmp(mime, "application/octet-stream")) { @@ -1302,6 +1323,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { uint16_t sample_size = U16_AT(&buffer[18]); uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; + if (!mLastTrack) { + return ERROR_MALFORMED; + } if (chunk_type != FOURCC('e', 'n', 'c', 'a')) { // if the chunk type is enca, we'll get the type from the sinf/frma box later mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); @@ -1397,6 +1421,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // printf("*** coding='%s' width=%d height=%d\n", // chunk, width, height); + if (!mLastTrack) { + return ERROR_MALFORMED; + } if (chunk_type != FOURCC('e', 'n', 'c', 'v')) { // if the chunk type is encv, we'll get the type from the sinf/frma box later mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); @@ -1427,6 +1454,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 't', 'c', 'o'): case FOURCC('c', 'o', '6', '4'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setChunkOffsetParams( chunk_type, data_offset, chunk_data_size); @@ -1441,6 +1471,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 't', 's', 'c'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setSampleToChunkParams( data_offset, chunk_data_size); @@ -1456,6 +1489,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 't', 's', 'z'): case FOURCC('s', 't', 'z', '2'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setSampleSizeParams( chunk_type, data_offset, chunk_data_size); @@ -1510,6 +1546,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 't', 't', 's'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setTimeToSampleParams( data_offset, chunk_data_size); @@ -1524,6 +1563,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('c', 't', 't', 's'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setCompositionTimeToSampleParams( data_offset, chunk_data_size); @@ -1538,6 +1580,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 't', 's', 's'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setSyncSampleParams( data_offset, chunk_data_size); @@ -1552,6 +1597,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 'a', 'i', 'z'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setSampleAuxiliaryInformationSizeParams( data_offset, chunk_data_size, mDrmScheme); @@ -1566,6 +1614,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 'a', 'i', 'o'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } status_t err = mLastTrack->sampleTable->setSampleAuxiliaryInformationOffsetParams( data_offset, chunk_data_size, mDrmScheme); @@ -1634,6 +1685,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_MALFORMED; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setData( kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); @@ -1666,6 +1720,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setData( kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size); @@ -1698,6 +1755,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); *offset += chunk_size; @@ -1860,6 +1920,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // shall be 'text'. We also want to support 'sbtl' handler type // for a practical reason as various MPEG4 containers use it. if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) { + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP); } @@ -1869,6 +1932,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('t', 'x', '3', 'g'): { + if (!mLastTrack) { + return ERROR_MALFORMED; + } uint32_t type; const void *data; size_t size = 0; @@ -1970,6 +2036,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { void MPEG4Extractor::storeEditList() { if (mHeaderTimescale == 0 || + !mLastTrack || mLastTrack->timescale == 0) { return; } @@ -2109,6 +2176,9 @@ status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { mSidxDuration = total_duration * 1000000 / timeScale; ALOGV("duration: %lld", mSidxDuration); + if (!mLastTrack) { + return ERROR_MALFORMED; + } int64_t metaDuration; if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) { mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration); @@ -2178,6 +2248,9 @@ status_t MPEG4Extractor::parseTrackHeader( return ERROR_UNSUPPORTED; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setInt32(kKeyTrackID, id); size_t matrixOffset = dynSize + 16; @@ -2359,6 +2432,9 @@ status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { int32_t delay, padding; if (sscanf(mLastCommentData, " %*x %x %x %*x", &delay, &padding) == 2) { + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); mLastTrack->meta->setInt32(kKeyEncoderPadding, padding); } @@ -2480,12 +2556,18 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( if (objectTypeIndication == 0xe1) { // This isn't MPEG4 audio at all, it's QCELP 14k... + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); return OK; } if (objectTypeIndication == 0x6b || objectTypeIndication == 0x69) { // The media subtype is MP3 audio + if (!mLastTrack) { + return ERROR_MALFORMED; + } mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); } @@ -2521,7 +2603,10 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( } if (objectType >= 1 && objectType <= 4) { - mLastTrack->meta->setInt32(kKeyAACProfile, objectType); + if (!mLastTrack) { + return ERROR_MALFORMED; + } + mLastTrack->meta->setInt32(kKeyAACProfile, objectType); } uint32_t freqIndex = br.getBits(4); @@ -2565,6 +2650,9 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( return ERROR_UNSUPPORTED; } + if (!mLastTrack) { + return ERROR_MALFORMED; + } int32_t prevSampleRate; CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));