Last active
August 29, 2015 14:26
-
-
Save jankowskib/07906c221d214696e65e to your computer and use it in GitHub Desktop.
Stagefright explioit patch for Mediateks (4.4.2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From feb0e93c1ec4e980a01293ec418db25a25aded1f Mon Sep 17 00:00:00 2001 | |
From: Bartosz J <thug1337@gmail.com> | |
Date: Thu, 6 Aug 2015 16:01:57 +0200 | |
Subject: [PATCH] Fix Stagefright exploits | |
Signed-off-by: Bartosz J <thug1337@gmail.com> | |
diff --git a/media/libstagefright/ESDS.cpp b/media/libstagefright/ESDS.cpp | |
index 103105d..b008df1 100644 | |
--- a/media/libstagefright/ESDS.cpp | |
+++ b/media/libstagefright/ESDS.cpp | |
@@ -179,6 +179,9 @@ status_t ESDS::parseESDescriptor(size_t offset, size_t size) { | |
--size; | |
if (streamDependenceFlag) { | |
+ if (size < 2) | |
+ return ERROR_MALFORMED; | |
+ | |
offset += 2; | |
size -= 2; | |
} | |
@@ -188,11 +191,18 @@ status_t ESDS::parseESDescriptor(size_t offset, size_t size) { | |
return ERROR_MALFORMED; | |
} | |
unsigned URLlength = mData[offset]; | |
+ | |
+ if (URLlength >= size) | |
+ return ERROR_MALFORMED; | |
+ | |
offset += URLlength + 1; | |
size -= URLlength + 1; | |
} | |
if (OCRstreamFlag) { | |
+ if (size < 2) | |
+ return ERROR_MALFORMED; | |
+ | |
offset += 2; | |
size -= 2; | |
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp | |
index 88d7705..bd181cb 100644 | |
--- a/media/libstagefright/MPEG4Extractor.cpp | |
+++ b/media/libstagefright/MPEG4Extractor.cpp | |
@@ -903,6 +903,9 @@ status_t MPEG4Extractor::parseDrmSINFMOOV(off64_t *offset, off64_t data_offset) | |
uint32_t size = U32_AT(&buf[36]); | |
uint8_t *data = new uint8_t[size]; | |
+ if (data == NULL) { | |
+ return ERROR_MALFORMED; | |
+ } | |
memset(data, 0, size); | |
if (mDataSource->readAt(data_offset+40, data, size) != size) { | |
return ERROR_IO; | |
@@ -946,6 +949,8 @@ status_t MPEG4Extractor::parseDrmSINFTrack(off64_t *offset, off64_t data_offset) | |
uint32_t Algor = U32_AT(&buf[20]) >> 8; | |
uint8_t IV_Size = buf[23]; | |
ALOGI("Algor:%d, IV_Size:%d", Algor, IV_Size); | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, IV_Size); | |
// encode KID for base64 | |
@@ -1336,6 +1341,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
mDataSource = cachedSource; | |
} | |
} | |
+ | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
mLastTrack->sampleTable = new SampleTable(mDataSource); | |
} | |
@@ -1578,6 +1586,10 @@ 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; | |
@@ -1631,7 +1643,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) { | |
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); | |
@@ -1728,6 +1743,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
int64_t duration; | |
int32_t samplerate; | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
if (mLastTrack->meta->findInt64(kKeyDuration, &duration) && | |
mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) { | |
@@ -1773,6 +1791,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
else if (entry_count == 2) | |
ALOGW("edit list entry_count=2, Assume the second entry is the duration of the track and normal play"); | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
mLastTrack->mElstEntryCount = entry_count; | |
mLastTrack->mElstEntries = new Track::ElstEntry[entry_count]; | |
if (version == 1) { | |
@@ -1844,6 +1865,8 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
if (mDataSource->readAt(data_offset, buffer, 26) < 26) { | |
return ERROR_IO; | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
const char* mtk_livephoto_tag = "MTK-live-photo:"; | |
if (!memcmp(mtk_livephoto_tag, buffer+6, 16)) { | |
int32_t mtk_livephoto_mode = U32_AT(&buffer[22]); | |
@@ -1917,9 +1940,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
if (mDataSource->readAt(data_offset, buffer, 16) < 16) { | |
return ERROR_IO; | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
const char* mtk_hevc_tag = "HEVC_MTK"; | |
if (!memcmp(mtk_hevc_tag, buffer+8, 8)) { | |
ALOGI("hevc_mtk"); | |
+ | |
mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC); | |
} | |
} | |
@@ -1958,7 +1984,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
< (ssize_t)sizeof(timescale)) { | |
return ERROR_IO; | |
} | |
- | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
mLastTrack->timescale = ntohl(timescale); | |
int64_t duration = 0; | |
@@ -2065,6 +2093,10 @@ 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)); | |
#ifdef MTK_SUBTITLE_SUPPORT | |
if(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) && strcasecmp(mime, "application/octet-stream") && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_VOBSUB)) | |
@@ -2114,6 +2146,8 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
#endif | |
#endif | |
{ | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
#ifndef ANDROID_DEFAULT_CODE//hai.li | |
mHasAudio = true; | |
mLastTrack->mIsAudio = true; | |
@@ -2148,6 +2182,10 @@ 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; | |
+ | |
#ifndef ANDROID_DEFAULT_CODE | |
uint16_t versions = U16_AT(&buffer[8]); | |
#ifdef MTK_AUDIO_RAW_SUPPORT | |
@@ -2294,6 +2332,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; | |
+ | |
#ifndef ANDROID_DEFAULT_CODE | |
#ifdef MTK_VIDEO_HEVC_SUPPORT | |
const char *mime; | |
@@ -2343,6 +2384,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
case FOURCC('s', 't', 'c', 'o'): | |
case FOURCC('c', 'o', '6', '4'): | |
{ | |
+ if (!mLastTrack || !mLastTrack->sampleTable.get()) | |
+ return ERROR_MALFORMED; | |
+ | |
status_t err = | |
mLastTrack->sampleTable->setChunkOffsetParams( | |
chunk_type, data_offset, chunk_data_size); | |
@@ -2357,6 +2401,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
case FOURCC('s', 't', 's', 'c'): | |
{ | |
+ if (!mLastTrack || !mLastTrack->sampleTable.get()) | |
+ return ERROR_MALFORMED; | |
+ | |
status_t err = | |
mLastTrack->sampleTable->setSampleToChunkParams( | |
data_offset, chunk_data_size); | |
@@ -2372,6 +2419,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
case FOURCC('s', 't', 's', 'z'): | |
case FOURCC('s', 't', 'z', '2'): | |
{ | |
+ if (!mLastTrack || !mLastTrack->sampleTable.get()) | |
+ return ERROR_MALFORMED; | |
+ | |
status_t err = | |
mLastTrack->sampleTable->setSampleSizeParams( | |
chunk_type, data_offset, chunk_data_size); | |
@@ -2488,6 +2538,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
case FOURCC('s', 't', 't', 's'): | |
{ | |
+ if (!mLastTrack || !mLastTrack->sampleTable.get()) | |
+ return ERROR_MALFORMED; | |
+ | |
#ifndef ANDROID_DEFAULT_CODE | |
status_t err = | |
mLastTrack->sampleTable->setTimeToSampleParams( | |
@@ -2519,6 +2572,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
case FOURCC('c', 't', 't', 's'): | |
{ | |
+ if (!mLastTrack || !mLastTrack->sampleTable.get()) | |
+ return ERROR_MALFORMED; | |
+ | |
#ifndef ANDROID_DEFAULT_CODE | |
status_t err = | |
mLastTrack->sampleTable->setCompositionTimeToSampleParams( | |
@@ -2538,6 +2594,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
case FOURCC('s', 't', 's', 's'): | |
{ | |
+ if (!mLastTrack || !mLastTrack->sampleTable.get()) | |
+ return ERROR_MALFORMED; | |
+ | |
#ifndef ANDROID_DEFAULT_CODE // ALPS00779876: Audio track doesn't need 'stss' table, each frame is sync frame | |
const char *mime; | |
mLastTrack->meta->findCString(kKeyMIMEType, &mime); | |
@@ -2604,6 +2663,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
return ERROR_MALFORMED; | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
uint8_t *buffer = (uint8_t *)malloc(chunk_data_size); | |
if (buffer == NULL) { | |
return -ENOMEM; | |
@@ -2615,6 +2677,8 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
ALOGE("ERROR_IO, LINE=%d", __LINE__); | |
return ERROR_IO; | |
} | |
+ | |
+ | |
mLastTrack->meta->setData(kKeyMPEG4VOS, 0,buffer,chunk_data_size); | |
*offset += chunk_size; | |
free(buffer); | |
@@ -2667,6 +2731,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
return ERROR_MALFORMED; | |
} | |
#endif | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
mLastTrack->meta->setData( | |
kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); | |
@@ -2767,6 +2834,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
data_offset, buffer->data(), chunk_data_size) < chunk_data_size) { | |
return ERROR_IO; | |
} | |
+ | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
#ifndef ANDROID_DEFAULT_CODE | |
#ifdef MTK_VIDEO_HEVC_SUPPORT | |
uint8_t *ptr1 = (uint8_t *)buffer->data(); | |
@@ -2817,7 +2888,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
data_offset, buffer, chunk_data_size) < chunk_data_size) { | |
return ERROR_IO; | |
} | |
- | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); | |
*offset += chunk_size; | |
@@ -2949,6 +3022,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
return ERROR_IO; | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
uint32_t type = ntohl(buffer); | |
// For the 3GPP file format, the handler-type within the 'hdlr' box | |
// shall be 'text'. We also want to support 'sbtl' handler type | |
@@ -2975,13 +3051,22 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
uint32_t type; | |
const void *data; | |
size_t size = 0; | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
if (!mLastTrack->meta->findData( | |
kKeyTextFormatData, &type, &data, &size)) { | |
size = 0; | |
} | |
- uint8_t *buffer = new uint8_t[size + chunk_size]; | |
- | |
+ if (SIZE_MAX - chunk_size <= size) | |
+ return ERROR_MALFORMED; | |
+ | |
+ uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size]; | |
+ if (buffer == NULL) { | |
+ return ERROR_MALFORMED; | |
+ } | |
+ | |
if (size > 0) { | |
memcpy(buffer, data, size); | |
} | |
@@ -3008,12 +3093,17 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | |
if (mFileMetaData != NULL) { | |
ALOGV("chunk_data_size = %lld and data_offset = %lld", | |
chunk_data_size, data_offset); | |
+ | |
+ if (chunk_data_size >= SIZE_MAX - 1) | |
+ return ERROR_MALFORMED; | |
sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1); | |
if (mDataSource->readAt( | |
data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) { | |
return ERROR_IO; | |
} | |
const int kSkipBytesOfDataBox = 16; | |
+ if (chunk_data_size <= kSkipBytesOfDataBox) | |
+ return ERROR_MALFORMED; | |
mFileMetaData->setData( | |
kKeyAlbumArt, MetaData::TYPE_NONE, | |
buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); | |
@@ -3224,6 +3314,8 @@ status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { | |
if (!mDataSource->getUInt32(offset + 8, &timeScale)) { | |
return ERROR_MALFORMED; | |
} | |
+ if (timeScale < 1) | |
+ return ERROR_MALFORMED; | |
ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); | |
uint64_t earliestPresentationTime; | |
@@ -3305,6 +3397,9 @@ status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { | |
mSidxEntries.add(se); | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
mSidxDuration = total_duration * 1000000 / timeScale; | |
ALOGV("duration: %lld", mSidxDuration); | |
@@ -3358,6 +3453,9 @@ status_t MPEG4Extractor::parseTrackHeader( | |
return ERROR_UNSUPPORTED; | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
mLastTrack->meta->setInt32(kKeyTrackID, id); | |
size_t matrixOffset = dynSize + 16; | |
@@ -3412,6 +3510,9 @@ status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { | |
} | |
uint8_t *buffer = new uint8_t[size + 1]; | |
+ if (buffer == NULL) { | |
+ return ERROR_MALFORMED; | |
+ } | |
if (mDataSource->readAt( | |
offset, buffer, size) != (ssize_t)size) { | |
delete[] buffer; | |
@@ -3536,6 +3637,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); | |
} | |
@@ -3692,6 +3796,9 @@ 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); | |
#ifndef ANDROID_DEFAULT_CODE | |
mLastTrack->skipTrack = true; | |
@@ -3701,6 +3808,8 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( | |
} | |
#ifndef ANDROID_DEFAULT_CODE //xingyu.zhou | |
if (objectTypeIndication == 0x6B || objectTypeIndication == 0x69) { | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); | |
mLastTrack->meta->setInt32(kKeyCodecInfoIsInFirstFrame, true); | |
return OK; | |
@@ -3746,6 +3855,8 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( | |
} | |
#ifndef ANDROID_DEFAULT_CODE | |
ALOGD("objectType:%d", objectType); | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
mLastTrack->meta->setInt32(kKeyAacObjType, objectType); | |
#endif | |
uint32_t freqIndex = br.getBits(4); | |
@@ -3789,6 +3900,9 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( | |
return ERROR_UNSUPPORTED; | |
} | |
+ if (!mLastTrack) | |
+ return ERROR_MALFORMED; | |
+ | |
int32_t prevSampleRate; | |
CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); | |
@@ -4244,7 +4358,7 @@ status_t MPEG4Extractor::getFirstNal(Track *track, size_t *nal_offset, size_t *n | |
ALOGE("incomplete first NAL unit.frame_size=%d, nalLengthSize=%d, nal_size=%d", frame_size, nalLengthSize, *nal_size); | |
return ERROR_MALFORMED; | |
} | |
-/* | |
+ | |
nal_data = malloc(nal_size); | |
if (NULL == nal_data) { | |
@@ -4258,8 +4372,6 @@ status_t MPEG4Extractor::getFirstNal(Track *track, size_t *nal_offset, size_t *n | |
ALOGE("read first nal fail!!"); | |
return ERROR_IO; | |
} | |
-*/ | |
-/* | |
*nal_offset = frame_offset + nalLengthSize; | |
ALOGD("First Nal offset=%d, size=%d", *nal_offset, *nal_size); | |
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp | |
index 976ea2a..66335ad 100644 | |
--- a/media/libstagefright/SampleTable.cpp | |
+++ b/media/libstagefright/SampleTable.cpp | |
@@ -269,9 +269,15 @@ status_t SampleTable::setSampleToChunkParams( | |
return ERROR_MALFORMED; | |
} | |
+ if (SIZE_MAX / sizeof(SampleToChunkEntry) <= mNumSampleToChunkOffsets) | |
+ return ERROR_OUT_OF_RANGE; | |
+ | |
mSampleToChunkEntries = | |
- new SampleToChunkEntry[mNumSampleToChunkOffsets]; | |
- | |
+ new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets]; | |
+ | |
+ if (!mSampleToChunkEntries) | |
+ return ERROR_OUT_OF_RANGE; | |
+ | |
for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { | |
uint8_t buffer[12]; | |
if (mDataSource->readAt( | |
@@ -378,8 +384,16 @@ status_t SampleTable::setTimeToSampleParams( | |
} | |
mTimeToSampleCount = U32_AT(&header[4]); | |
- mTimeToSample = new uint32_t[mTimeToSampleCount * 2]; | |
- | |
+ uint64_t allocSize = mTimeToSampleCount * 2 * (uint64_t)sizeof(uint32_t); | |
+ if (allocSize > SIZE_MAX) { | |
+ return ERROR_OUT_OF_RANGE; | |
+ } | |
+ | |
+ mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2]; | |
+ | |
+ if (!mTimeToSample) | |
+ return ERROR_OUT_OF_RANGE; | |
+ | |
size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2; | |
if (mDataSource->readAt( | |
data_offset + 8, mTimeToSample, size) < (ssize_t)size) { | |
@@ -435,8 +449,16 @@ status_t SampleTable::setCompositionTimeToSampleParams( | |
#endif | |
mNumCompositionTimeDeltaEntries = numEntries; | |
- mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries]; | |
+ uint64_t allocSize = numEntries * 2 * (uint64_t)sizeof(uint32_t); | |
+ if (allocSize > SIZE_MAX) { | |
+ return ERROR_OUT_OF_RANGE; | |
+ } | |
+ | |
+ mCompositionTimeDeltaEntries = new (std::nothrow) uint32_t[2 * numEntries]; | |
+ if (!mCompositionTimeDeltaEntries) | |
+ return ERROR_OUT_OF_RANGE; | |
+ | |
if (mDataSource->readAt( | |
data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8) | |
< (ssize_t)numEntries * 8) { | |
@@ -528,8 +550,16 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) | |
if (mNumSyncSamples < 2) { | |
ALOGV("Table of sync samples is empty or has only a single entry!"); | |
} | |
- | |
- mSyncSamples = new uint32_t[mNumSyncSamples]; | |
+ | |
+ uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t); | |
+ if (allocSize > SIZE_MAX) { | |
+ return ERROR_OUT_OF_RANGE; | |
+ } | |
+ | |
+ mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples]; | |
+ if (!mSyncSamples) | |
+ return ERROR_OUT_OF_RANGE; | |
+ | |
size_t size = mNumSyncSamples * sizeof(uint32_t); | |
if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size) | |
!= (ssize_t)size) { | |
@@ -597,8 +627,11 @@ void SampleTable::buildSampleEntriesTable() { | |
return; | |
} | |
- mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes]; | |
+ mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes]; | |
+ if (!mSampleTimeEntries) | |
+ return; | |
+ | |
uint32_t sampleIndex = 0; | |
uint32_t sampleTime = 0; | |
-- | |
Gitg | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment