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

Commit f7201862 authored by Pawin Vongmasa's avatar Pawin Vongmasa Committed by android-build-merger
Browse files

Merge "SampleTable.cpp: Prevent corrupted stts block from causing excessive...

Merge "SampleTable.cpp: Prevent corrupted stts block from causing excessive memory allocation." into klp-dev am: 59645279 am: e896c41d am: a0970c9f am: ab727635
am: 8cf4bf38

* commit '8cf4bf38':
  SampleTable.cpp: Prevent corrupted stts block from causing excessive memory allocation.

Change-Id: Ie35530048156f7f5c4fd36c5901f6de4e1374f56
parents 8e460160 8cf4bf38
Loading
Loading
Loading
Loading
+60 −1
Original line number Original line Diff line number Diff line
@@ -19,7 +19,7 @@
#define DATA_SOURCE_H_
#define DATA_SOURCE_H_


#include <sys/types.h>
#include <sys/types.h>

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/Errors.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/KeyedVector.h>
@@ -66,6 +66,20 @@ public:
    bool getUInt32(off64_t offset, uint32_t *x);
    bool getUInt32(off64_t offset, uint32_t *x);
    bool getUInt64(off64_t offset, uint64_t *x);
    bool getUInt64(off64_t offset, uint64_t *x);


    // Reads in "count" entries of type T into vector *x.
    // Returns true if "count" entries can be read.
    // If fewer than "count" entries can be read, return false. In this case,
    // the output vector *x will still have those entries that were read. Call
    // x->size() to obtain the number of entries read.
    // The optional parameter chunkSize specifies how many entries should be
    // read from the data source at one time into a temporary buffer. Increasing
    // chunkSize can improve the performance at the cost of extra memory usage.
    // The default value for chunkSize is set to read at least 4k bytes at a
    // time, depending on sizeof(T).
    template <typename T>
    bool getVector(off64_t offset, Vector<T>* x, size_t count,
                   size_t chunkSize = (4095 / sizeof(T)) + 1);

    // May return ERROR_UNSUPPORTED.
    // May return ERROR_UNSUPPORTED.
    virtual status_t getSize(off64_t *size);
    virtual status_t getSize(off64_t *size);


@@ -116,6 +130,51 @@ private:
    DataSource &operator=(const DataSource &);
    DataSource &operator=(const DataSource &);
};
};


template <typename T>
bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count,
                           size_t chunkSize)
{
    x->clear();
    if (chunkSize == 0) {
        return false;
    }
    if (count == 0) {
        return true;
    }

    T tmp[chunkSize];
    ssize_t numBytesRead;
    size_t numBytesPerChunk = chunkSize * sizeof(T);
    size_t i;

    for (i = 0; i + chunkSize < count; i += chunkSize) {
        // This loops is executed when more than chunkSize records need to be
        // read.
        numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk);
        if (numBytesRead == -1) { // If readAt() returns -1, there is an error.
            return false;
        }
        if (numBytesRead < numBytesPerChunk) {
            // This case is triggered when the stream ends before the whole
            // chunk is read.
            x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
            return false;
        }
        x->appendArray(tmp, chunkSize);
        offset += numBytesPerChunk;
    }

    // There are (count - i) more records to read.
    // Right now, (count - i) <= chunkSize.
    // We do the same thing as above, but with chunkSize replaced by count - i.
    numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T));
    if (numBytesRead == -1) {
        return false;
    }
    x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
    return x->size() == count;
}

}  // namespace android
}  // namespace android


#endif  // DATA_SOURCE_H_
#endif  // DATA_SOURCE_H_
+19 −15
Original line number Original line Diff line number Diff line
@@ -122,7 +122,7 @@ SampleTable::SampleTable(const sp<DataSource> &source)
      mDefaultSampleSize(0),
      mDefaultSampleSize(0),
      mNumSampleSizes(0),
      mNumSampleSizes(0),
      mTimeToSampleCount(0),
      mTimeToSampleCount(0),
      mTimeToSample(NULL),
      mTimeToSample(),
      mSampleTimeEntries(NULL),
      mSampleTimeEntries(NULL),
      mCompositionTimeDeltaEntries(NULL),
      mCompositionTimeDeltaEntries(NULL),
      mNumCompositionTimeDeltaEntries(0),
      mNumCompositionTimeDeltaEntries(0),
@@ -151,9 +151,6 @@ SampleTable::~SampleTable() {
    delete[] mSampleTimeEntries;
    delete[] mSampleTimeEntries;
    mSampleTimeEntries = NULL;
    mSampleTimeEntries = NULL;


    delete[] mTimeToSample;
    mTimeToSample = NULL;

    delete mSampleIterator;
    delete mSampleIterator;
    mSampleIterator = NULL;
    mSampleIterator = NULL;
}
}
@@ -162,7 +159,7 @@ bool SampleTable::isValid() const {
    return mChunkOffsetOffset >= 0
    return mChunkOffsetOffset >= 0
        && mSampleToChunkOffset >= 0
        && mSampleToChunkOffset >= 0
        && mSampleSizeOffset >= 0
        && mSampleSizeOffset >= 0
        && mTimeToSample != NULL;
        && !mTimeToSample.empty();
}
}


status_t SampleTable::setChunkOffsetParams(
status_t SampleTable::setChunkOffsetParams(
@@ -326,7 +323,7 @@ status_t SampleTable::setSampleSizeParams(


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


@@ -342,22 +339,29 @@ status_t SampleTable::setTimeToSampleParams(
    }
    }


    mTimeToSampleCount = U32_AT(&header[4]);
    mTimeToSampleCount = U32_AT(&header[4]);
    uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
    if ((uint64_t)mTimeToSampleCount >
    if (allocSize > SIZE_MAX) {
        (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) {
        // Choose this bound because
        // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
        //    time-to-sample entry in the time-to-sample table.
        // 2) mTimeToSampleCount is the number of entries of the time-to-sample
        //    table.
        // 3) We hope that the table size does not exceed UINT32_MAX.
        ALOGE("  Error: Time-to-sample table size too large.");
        return ERROR_OUT_OF_RANGE;
        return ERROR_OUT_OF_RANGE;
    }
    }
    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];


    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
    // Note: At this point, we know that mTimeToSampleCount * 2 will not
    if (mDataSource->readAt(
    // overflow because of the above condition.
                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
    if (!mDataSource->getVector(data_offset + 8, &mTimeToSample,
                                mTimeToSampleCount * 2)) {
        ALOGE("  Error: Incomplete data read for time-to-sample table.");
        return ERROR_IO;
        return ERROR_IO;
    }
    }


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

    return OK;
    return OK;
}
}


+2 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/RefBase.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
#include <utils/threads.h>
#include <utils/Vector.h>


namespace android {
namespace android {


@@ -111,7 +112,7 @@ private:
    uint32_t mNumSampleSizes;
    uint32_t mNumSampleSizes;


    uint32_t mTimeToSampleCount;
    uint32_t mTimeToSampleCount;
    uint32_t *mTimeToSample;
    Vector<uint32_t> mTimeToSample;


    struct SampleTimeEntry {
    struct SampleTimeEntry {
        uint32_t mSampleIndex;
        uint32_t mSampleIndex;