Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12de2b95 authored by wuhuang's avatar wuhuang Committed by Marco Nelissen
Browse files

mp4 extractor: Too big sample timestamp can lead to overflow Exception.

seekTo in the video track will query the timestamp, PTS of the sample according to the seekTo time. The PTS value greater than UNIT_32_Max can cause the uint_32 overflow during the calculation.

Test: To test the videoes that the PTS value is greater than UNIT_32_Max, find out the relative overflows in the logs.
Change-Id: I796e3abcd7d0aad1614c07119a3012fc641266d8
parent 8c461da1
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -594,7 +594,7 @@ media_status_t MPEG4Extractor::getTrackMetaData(
                }
            } else {
                uint32_t sampleIndex;
                uint32_t sampleTime;
                uint64_t sampleTime;
                if (track->timescale != 0 &&
                        track->sampleTable->findThumbnailSample(&sampleIndex) == OK
                        && track->sampleTable->getMetaDataForSample(
@@ -4503,7 +4503,7 @@ status_t MPEG4Source::init() {
    }

    if (!strncasecmp("video/", mime, 6)) {
        uint32_t firstSampleCTS = 0;
        uint64_t firstSampleCTS = 0;
        err = mSampleTable->getMetaDataForSample(0, NULL, NULL, &firstSampleCTS);
        // Start offset should be less or equal to composition time of first sample.
        // Composition time stamp of first sample cannot be negative.
@@ -5349,7 +5349,7 @@ media_status_t MPEG4Source::read(
                        sampleIndex, &syncSampleIndex, findFlags);
            }

            uint32_t sampleTime;
            uint64_t sampleTime;
            if (err == OK) {
                err = mSampleTable->getMetaDataForSample(
                        sampleIndex, NULL, NULL, &sampleTime);
@@ -5399,7 +5399,7 @@ media_status_t MPEG4Source::read(

    off64_t offset = 0;
    size_t size = 0;
    uint32_t cts, stts;
    uint64_t cts, stts;
    bool isSyncSample;
    bool newBuffer = false;
    if (mBuffer == NULL) {
+5 −5
Original line number Diff line number Diff line
@@ -301,7 +301,7 @@ status_t SampleIterator::getSampleSizeDirect(
}

status_t SampleIterator::findSampleTimeAndDuration(
        uint32_t sampleIndex, uint32_t *time, uint32_t *duration) {
        uint32_t sampleIndex, uint64_t *time, uint64_t *duration) {
    if (sampleIndex >= mTable->mNumSampleSizes) {
        return ERROR_OUT_OF_RANGE;
    }
@@ -314,8 +314,8 @@ status_t SampleIterator::findSampleTimeAndDuration(
            break;
        }
        if (mTimeToSampleIndex == mTable->mTimeToSampleCount ||
            (mTTSDuration != 0 && mTTSCount > UINT32_MAX / mTTSDuration) ||
            mTTSSampleTime > UINT32_MAX - (mTTSCount * mTTSDuration)) {
            (mTTSDuration != 0 && mTTSCount > UINT64_MAX / mTTSDuration) ||
            mTTSSampleTime > UINT64_MAX - (mTTSCount * mTTSDuration)) {
            return ERROR_OUT_OF_RANGE;
        }

@@ -341,8 +341,8 @@ status_t SampleIterator::findSampleTimeAndDuration(
    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);
            (offset > 0 && *time > UINT64_MAX - offset)) {
        ALOGE("%llu + %d would overflow", (unsigned long long) *time, offset);
        return ERROR_OUT_OF_RANGE;
    }
    if (offset > 0) {
+7 −7
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ struct SampleIterator {
    uint32_t getDescIndex() const { return mChunkDesc; }
    off64_t getSampleOffset() const { return mCurrentSampleOffset; }
    size_t getSampleSize() const { return mCurrentSampleSize; }
    uint32_t getSampleTime() const { return mCurrentSampleTime; }
    uint32_t getSampleDuration() const { return mCurrentSampleDuration; }
    uint64_t getSampleTime() const { return mCurrentSampleTime; }
    uint64_t getSampleDuration() const { return mCurrentSampleDuration; }

    uint32_t getLastSampleIndexInChunk() const {
        return mCurrentSampleIndex + mSamplesPerChunk -
@@ -63,20 +63,20 @@ private:

    uint32_t mTimeToSampleIndex;
    uint32_t mTTSSampleIndex;
    uint32_t mTTSSampleTime;
    uint64_t mTTSSampleTime;
    uint32_t mTTSCount;
    uint32_t mTTSDuration;
    uint64_t mTTSDuration;

    uint32_t mCurrentSampleIndex;
    off64_t mCurrentSampleOffset;
    size_t mCurrentSampleSize;
    uint32_t mCurrentSampleTime;
    uint32_t mCurrentSampleDuration;
    uint64_t mCurrentSampleTime;
    uint64_t mCurrentSampleDuration;

    void reset();
    status_t findChunkRange(uint32_t sampleIndex);
    status_t getChunkOffset(uint32_t chunk, off64_t *offset);
    status_t findSampleTimeAndDuration(uint32_t sampleIndex, uint32_t *time, uint32_t *duration);
    status_t findSampleTimeAndDuration(uint32_t sampleIndex, uint64_t *time, uint64_t *duration);

    SampleIterator(const SampleIterator &);
    SampleIterator &operator=(const SampleIterator &);
+15 −15
Original line number Diff line number Diff line
@@ -614,7 +614,7 @@ status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    return OK;
}

uint32_t abs_difference(uint32_t time1, uint32_t time2) {
uint32_t abs_difference(uint64_t time1, uint64_t time2) {
    return time1 > time2 ? time1 - time2 : time2 - time1;
}

@@ -662,7 +662,7 @@ void SampleTable::buildSampleEntriesTable() {
    }

    uint32_t sampleIndex = 0;
    uint32_t sampleTime = 0;
    uint64_t sampleTime = 0;

    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
        uint32_t n = mTimeToSample[2 * i];
@@ -684,13 +684,13 @@ void SampleTable::buildSampleEntriesTable() {
                        (compTimeDelta == INT32_MIN ?
                                INT32_MAX : uint32_t(-compTimeDelta)))
                        || (compTimeDelta > 0 &&
                                sampleTime > UINT32_MAX - compTimeDelta)) {
                    ALOGE("%u + %d would overflow, clamping",
                            sampleTime, compTimeDelta);
                                sampleTime > UINT64_MAX - compTimeDelta)) {
                    ALOGE("%llu + %d would overflow, clamping",
                            (unsigned long long) sampleTime, compTimeDelta);
                    if (compTimeDelta < 0) {
                        sampleTime = 0;
                    } else {
                        sampleTime = UINT32_MAX;
                        sampleTime = UINT64_MAX;
                    }
                    compTimeDelta = 0;
                }
@@ -701,10 +701,10 @@ void SampleTable::buildSampleEntriesTable() {
            }

            ++sampleIndex;
            if (sampleTime > UINT32_MAX - delta) {
                ALOGE("%u + %u would overflow, clamping",
                    sampleTime, delta);
                sampleTime = UINT32_MAX;
            if (sampleTime > UINT64_MAX - delta) {
                ALOGE("%llu + %u would overflow, clamping",
                    (unsigned long long) sampleTime, delta);
                sampleTime = UINT64_MAX;
            } else {
                sampleTime += delta;
            }
@@ -870,19 +870,19 @@ status_t SampleTable::findSyncSampleNear(
            if (err != OK) {
                return err;
            }
            uint32_t sample_time = mSampleIterator->getSampleTime();
            uint64_t sample_time = mSampleIterator->getSampleTime();

            err = mSampleIterator->seekTo(mSyncSamples[left]);
            if (err != OK) {
                return err;
            }
            uint32_t upper_time = mSampleIterator->getSampleTime();
            uint64_t upper_time = mSampleIterator->getSampleTime();

            err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
            if (err != OK) {
                return err;
            }
            uint32_t lower_time = mSampleIterator->getSampleTime();
            uint64_t lower_time = mSampleIterator->getSampleTime();

            // use abs_difference for safety
            if (abs_difference(upper_time, sample_time) >
@@ -955,9 +955,9 @@ status_t SampleTable::getMetaDataForSample(
        uint32_t sampleIndex,
        off64_t *offset,
        size_t *size,
        uint32_t *compositionTime,
        uint64_t *compositionTime,
        bool *isSyncSample,
        uint32_t *sampleDuration) {
        uint64_t *sampleDuration) {
    Mutex::Autolock autoLock(mLock);

    status_t err;
+3 −3
Original line number Diff line number Diff line
@@ -66,9 +66,9 @@ public:
            uint32_t sampleIndex,
            off64_t *offset,
            size_t *size,
            uint32_t *compositionTime,
            uint64_t *compositionTime,
            bool *isSyncSample = NULL,
            uint32_t *sampleDuration = NULL);
            uint64_t *sampleDuration = NULL);

    // call only after getMetaDataForSample has been called successfully.
    uint32_t getLastSampleIndexInChunk();
@@ -124,7 +124,7 @@ private:

    struct SampleTimeEntry {
        uint32_t mSampleIndex;
        uint32_t mCompositionTime;
        uint64_t mCompositionTime;
    };
    SampleTimeEntry *mSampleTimeEntries;