Commit message: None
CVE: CVE-2015-1538
CWE: CWE-189
Vulnerability description: Integer overflow in the SampleTable::setSampleToChunkParams function in SampleTable.cpp in libstagefright in Android before 5.1.1 LMY48I allows remote attackers to execute arbitrary code via crafted atoms in MP4 data that trigger an unchecked multiplication, aka internal bug 20139950, a related issue to CVE-2015-4496.

Project: Android

status_t SampleTable::setCompositionTimeToSampleParams(
 off64_t data_offset, size_t data_size) {
    ALOGI("There are reordered frames present.");

 if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
 return ERROR_MALFORMED;
 }

 uint8_t header[8];
 if (mDataSource->readAt(
                data_offset, header, sizeof(header))
 < (ssize_t)sizeof(header)) {
 return ERROR_IO;
 }

 if (U32_AT(header) != 0) {
 return ERROR_MALFORMED;
 }

 size_t numEntries = U32_AT(&header[4]);

 if (data_size != (numEntries + 1) * 8) {
 return ERROR_MALFORMED;
 }

    mNumCompositionTimeDeltaEntries = numEntries;
 uint64_t allocSize = numEntries * 2 * (uint64_t)sizeof(uint32_t);
 if (allocSize > SIZE_MAX) {
 return ERROR_OUT_OF_RANGE;
 }

    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];

 if (mDataSource->readAt(
                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
 < (ssize_t)numEntries * 8) {
 delete[] mCompositionTimeDeltaEntries;
        mCompositionTimeDeltaEntries = NULL;

 return ERROR_IO;
 }

 for (size_t i = 0; i < 2 * numEntries; ++i) {
        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
 }

    mCompositionDeltaLookup->setEntries(
            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);

 return OK;
}

Project: Android

status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
 if (mSyncSampleOffset >= 0 || data_size < 8) {
 return ERROR_MALFORMED;
 }

    mSyncSampleOffset = data_offset;

 uint8_t header[8];
 if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
 return ERROR_IO;
 }

 if (U32_AT(header) != 0) {
 return ERROR_MALFORMED;
 }

    mNumSyncSamples = U32_AT(&header[4]);

 if (mNumSyncSamples < 2) {
        ALOGV("Table of sync samples is empty or has only a single entry!");
 }

 uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t);
 if (allocSize > SIZE_MAX) {
 return ERROR_OUT_OF_RANGE;
 }

    mSyncSamples = new uint32_t[mNumSyncSamples];
 size_t size = mNumSyncSamples * sizeof(uint32_t);
 if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
 != (ssize_t)size) {
 return ERROR_IO;
 }

 for (size_t i = 0; i < mNumSyncSamples; ++i) {
        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
 }

 return OK;
}

Project: Android

status_t SampleTable::setTimeToSampleParams(
 off64_t data_offset, size_t data_size) {
 if (mTimeToSample != NULL || data_size < 8) {
 return ERROR_MALFORMED;
 }

 uint8_t header[8];
 if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
 return ERROR_IO;
 }

 if (U32_AT(header) != 0) {
 return ERROR_MALFORMED;
 }

    mTimeToSampleCount = U32_AT(&header[4]);
 uint64_t allocSize = mTimeToSampleCount * 2 * (uint64_t)sizeof(uint32_t);
 if (allocSize > SIZE_MAX) {
 return ERROR_OUT_OF_RANGE;
 }
    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];

 size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
 if (mDataSource->readAt(
                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
 return ERROR_IO;
 }

 for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
        mTimeToSample[i] = ntohl(mTimeToSample[i]);
 }

 return OK;
}