Commit message: None
CVE: CVE-2016-6722
CWE: CWE-200
Vulnerability description: An information disclosure vulnerability in libstagefright in Mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-11-01, and 7.0 before 2016-11-01 could enable a local malicious application to access data outside of its permission levels. This issue is rated as Moderate because it could be used to access sensitive data without permission. Android ID: A-31091777.

Project: Android

SampleIterator::SampleIterator(SampleTable *table)
 : mTable(table),
      mInitialized(false),
      mTimeToSampleIndex(0),
      mTTSSampleIndex(0),
      mTTSSampleTime(0),
      mTTSCount(0),
      mTTSDuration(0) {
    reset();
}

Project: Android

status_t SampleIterator::findChunkRange(uint32_t sampleIndex) {
    CHECK(sampleIndex >= mFirstChunkSampleIndex);

 while (sampleIndex >= mStopChunkSampleIndex) {
 if (mSampleToChunkIndex == mTable->mNumSampleToChunkOffsets) {
 return ERROR_OUT_OF_RANGE;
 }

        mFirstChunkSampleIndex = mStopChunkSampleIndex;

 const SampleTable::SampleToChunkEntry *entry =
 &mTable->mSampleToChunkEntries[mSampleToChunkIndex];

        mFirstChunk = entry->startChunk;
        mSamplesPerChunk = entry->samplesPerChunk;
        mChunkDesc = entry->chunkDesc;

 if (mSampleToChunkIndex + 1 < mTable->mNumSampleToChunkOffsets) {
            mStopChunk = entry[1].startChunk;

 if (mStopChunk < mFirstChunk ||
 (mStopChunk - mFirstChunk) > UINT32_MAX / mSamplesPerChunk ||
 ((mStopChunk - mFirstChunk) * mSamplesPerChunk >
                 UINT32_MAX - mFirstChunkSampleIndex)) {

 return ERROR_OUT_OF_RANGE;
 }
            mStopChunkSampleIndex =
                mFirstChunkSampleIndex
 + (mStopChunk - mFirstChunk) * mSamplesPerChunk;
 } else {
            mStopChunk = 0xffffffff;
            mStopChunkSampleIndex = 0xffffffff;
 }

 ++mSampleToChunkIndex;
 }

 return OK;
}

Project: Android

status_t SampleIterator::findSampleTimeAndDuration(
 uint32_t sampleIndex, uint32_t *time, uint32_t *duration) {
 if (sampleIndex >= mTable->mNumSampleSizes) {
 return ERROR_OUT_OF_RANGE;
 }

 while (sampleIndex >= mTTSSampleIndex + mTTSCount) {
 if (mTimeToSampleIndex == mTable->mTimeToSampleCount) {
 return ERROR_OUT_OF_RANGE;
 }

        mTTSSampleIndex += mTTSCount;
        mTTSSampleTime += mTTSCount * mTTSDuration;

        mTTSCount = mTable->mTimeToSample[2 * mTimeToSampleIndex];
        mTTSDuration = mTable->mTimeToSample[2 * mTimeToSampleIndex + 1];

 ++mTimeToSampleIndex;
 }

 *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);

 int32_t offset = mTable->getCompositionTimeOffset(sampleIndex);
 if ((offset < 0 && *time < (offset == INT32_MIN ?
            INT32_MAX : uint32_t(-offset))) ||
 (offset > 0 && *time > UINT32_MAX - offset)) {
        ALOGE("%u + %d would overflow", *time, offset);
 return ERROR_OUT_OF_RANGE;
 }
 if (offset > 0) {
 *time += offset;
 } else {
 *time -= (offset == INT32_MIN ? INT32_MAX : (-offset));
 }

 *duration = mTTSDuration;

 return OK;
}

Project: Android

status_t SampleIterator::getChunkOffset(uint32_t chunk, off64_t *offset) {
 *offset = 0;

 if (chunk >= mTable->mNumChunkOffsets) {
 return ERROR_OUT_OF_RANGE;
 }

 if (mTable->mChunkOffsetType == SampleTable::kChunkOffsetType32) {
 uint32_t offset32;

 if (mTable->mDataSource->readAt(
                    mTable->mChunkOffsetOffset + 8 + 4 * chunk,
 &offset32,
 sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
 return ERROR_IO;
 }

 *offset = ntohl(offset32);
 } else {
        CHECK_EQ(mTable->mChunkOffsetType, SampleTable::kChunkOffsetType64);

 uint64_t offset64;
 if (mTable->mDataSource->readAt(
                    mTable->mChunkOffsetOffset + 8 + 8 * chunk,
 &offset64,
 sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
 return ERROR_IO;
 }

 *offset = ntoh64(offset64);
 }

 return OK;
}

Project: Android

status_t SampleIterator::getSampleSizeDirect(
 uint32_t sampleIndex, size_t *size) {
 *size = 0;

 if (sampleIndex >= mTable->mNumSampleSizes) {
 return ERROR_OUT_OF_RANGE;
 }

 if (mTable->mDefaultSampleSize > 0) {
 *size = mTable->mDefaultSampleSize;
 return OK;
 }

 switch (mTable->mSampleSizeFieldSize) {
 case 32:
 {
 if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + 4 * sampleIndex,
                        size, sizeof(*size)) < (ssize_t)sizeof(*size)) {
 return ERROR_IO;
 }

 *size = ntohl(*size);
 break;
 }

 case 16:
 {
 uint16_t x;
 if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + 2 * sampleIndex,
 &x, sizeof(x)) < (ssize_t)sizeof(x)) {
 return ERROR_IO;
 }

 *size = ntohs(x);
 break;
 }

 case 8:
 {
 uint8_t x;
 if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + sampleIndex,
 &x, sizeof(x)) < (ssize_t)sizeof(x)) {
 return ERROR_IO;
 }

 *size = x;
 break;
 }

 default:
 {
            CHECK_EQ(mTable->mSampleSizeFieldSize, 4);

 uint8_t x;
 if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + sampleIndex / 2,
 &x, sizeof(x)) < (ssize_t)sizeof(x)) {
 return ERROR_IO;
 }

 *size = (sampleIndex & 1) ? x & 0x0f : x >> 4;
 break;
 }
 }

 return OK;
}

Project: Android

void SampleIterator::reset() {
    mSampleToChunkIndex = 0;
    mFirstChunk = 0;
    mFirstChunkSampleIndex = 0;
    mStopChunk = 0;
    mStopChunkSampleIndex = 0;
    mSamplesPerChunk = 0;
    mChunkDesc = 0;
}