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

Commit c6f2afc5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge changes...

Merge changes If449d3e3,I953bea9f,I9bb8c659,I25d4cf54,I48ba34b3,I96a9c437,I70c9e332,Ifdc3e743,Iba1011e9 into av-aosp.lnx.2.0-dev

* changes:
  DO NOT MERGE - stagefright: fix integer overflow error
  Impose a size bound for dynamically allocated tables in stbl.
  fix build
  SoftVPX: fix nFilledLen overflow
  Fix build
  Fix build
  SoftMP3: memset safely
  stagefright: fix possible stack overflow in AVCC reassemble
  omx: prevent input port enable/disable for software codecs
parents 5a7aa31c e801e126
Loading
Loading
Loading
Loading
+133 −32
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#include <limits>

#include "include/SampleTable.h"
#include "include/SampleIterator.h"

@@ -45,6 +47,8 @@ const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');

////////////////////////////////////////////////////////////////////////////////

const off64_t kMaxOffset = std::numeric_limits<off64_t>::max();

struct SampleTable::CompositionDeltaLookup {
    CompositionDeltaLookup();

@@ -123,7 +127,7 @@ SampleTable::SampleTable(const sp<DataSource> &source)
      mNumSampleSizes(0),
      mHasTimeToSample(false),
      mTimeToSampleCount(0),
      mTimeToSample(),
      mTimeToSample(NULL),
      mSampleTimeEntries(NULL),
      mCompositionTimeDeltaEntries(NULL),
      mNumCompositionTimeDeltaEntries(0),
@@ -132,7 +136,8 @@ SampleTable::SampleTable(const sp<DataSource> &source)
      mNumSyncSamples(0),
      mSyncSamples(NULL),
      mLastSyncSampleIndex(0),
      mSampleToChunkEntries(NULL) {
      mSampleToChunkEntries(NULL),
      mTotalSize(0) {
    mSampleIterator = new SampleIterator(this);
}

@@ -143,6 +148,9 @@ SampleTable::~SampleTable() {
    delete[] mSyncSamples;
    mSyncSamples = NULL;

    delete[] mTimeToSample;
    mTimeToSample = NULL;

    delete mCompositionDeltaLookup;
    mCompositionDeltaLookup = NULL;

@@ -229,27 +237,55 @@ status_t SampleTable::setSampleToChunkParams(

    mNumSampleToChunkOffsets = U32_AT(&header[4]);

    if ((data_size - 8) / 12 < mNumSampleToChunkOffsets) {
    if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) {
        return ERROR_MALFORMED;
    }

    if (SIZE_MAX / sizeof(SampleToChunkEntry) <= (size_t)mNumSampleToChunkOffsets)
    if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <=
            (uint64_t)mNumSampleToChunkOffsets) {
        ALOGE("Sample-to-chunk table size too large.");
        return ERROR_OUT_OF_RANGE;
    }

    mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
            sizeof(SampleToChunkEntry);
    if (mTotalSize > kMaxTotalSize) {
        ALOGE("Sample-to-chunk table size would make sample table too large.\n"
              "    Requested sample-to-chunk table size = %llu\n"
              "    Eventual sample table size >= %llu\n"
              "    Allowed sample table size = %llu\n",
              (unsigned long long)mNumSampleToChunkOffsets *
                      sizeof(SampleToChunkEntry),
              (unsigned long long)mTotalSize,
              (unsigned long long)kMaxTotalSize);
        return ERROR_OUT_OF_RANGE;
    }

    mSampleToChunkEntries =
        new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
    if (!mSampleToChunkEntries)
    if (!mSampleToChunkEntries) {
        ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
                (unsigned long long)mNumSampleToChunkOffsets);
        return ERROR_OUT_OF_RANGE;
    }

    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
        uint8_t buffer[12];
    if (mNumSampleToChunkOffsets == 0) {
        return OK;
    }

        if ((off64_t)(SIZE_MAX - 8 - (i * 12)) < mSampleToChunkOffset) {
    if ((off64_t)(kMaxOffset - 8 -
            ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
            < mSampleToChunkOffset) {
        return ERROR_MALFORMED;
    }

    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
        uint8_t buffer[sizeof(SampleToChunkEntry)];

        if (mDataSource->readAt(
                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
                    mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry),
                    buffer,
                    sizeof(buffer))
                != (ssize_t)sizeof(buffer)) {
            return ERROR_IO;
        }
@@ -350,28 +386,48 @@ status_t SampleTable::setTimeToSampleParams(
    }

    mTimeToSampleCount = U32_AT(&header[4]);
    if ((uint64_t)mTimeToSampleCount >
        (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) {
    if (mTimeToSampleCount > 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.");
        ALOGE("Time-to-sample table size too large.");
        return ERROR_OUT_OF_RANGE;
    }

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

    uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
    mTotalSize += allocSize;
    if (mTotalSize > kMaxTotalSize) {
        ALOGE("Time-to-sample table size would make sample table too large.\n"
              "    Requested time-to-sample table size = %llu\n"
              "    Eventual sample table size >= %llu\n"
              "    Allowed sample table size = %llu\n",
              (unsigned long long)allocSize,
              (unsigned long long)mTotalSize,
              (unsigned long long)kMaxTotalSize);
        return ERROR_OUT_OF_RANGE;
    }

    mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
    if (!mTimeToSample) {
        ALOGE("Cannot allocate time-to-sample table with %llu entries.",
                (unsigned long long)mTimeToSampleCount);
        return ERROR_OUT_OF_RANGE;
    }

    if (mDataSource->readAt(data_offset + 8, mTimeToSample,
            (size_t)allocSize) < (ssize_t)allocSize) {
        ALOGE("Incomplete data read for time-to-sample table.");
        return ERROR_IO;
    }

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

    mHasTimeToSample = true;
@@ -413,18 +469,33 @@ status_t SampleTable::setCompositionTimeToSampleParams(
    }

    mNumCompositionTimeDeltaEntries = numEntries;
    uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t);
    if (allocSize > UINT32_MAX) {
    uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
    if (allocSize > kMaxTotalSize) {
        ALOGE("Composition-time-to-sample table size too large.");
        return ERROR_OUT_OF_RANGE;
    }

    mTotalSize += allocSize;
    if (mTotalSize > kMaxTotalSize) {
        ALOGE("Composition-time-to-sample table would make sample table too large.\n"
              "    Requested composition-time-to-sample table size = %llu\n"
              "    Eventual sample table size >= %llu\n"
              "    Allowed sample table size = %llu\n",
              (unsigned long long)allocSize,
              (unsigned long long)mTotalSize,
              (unsigned long long)kMaxTotalSize);
        return ERROR_OUT_OF_RANGE;
    }

    mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
    if (!mCompositionTimeDeltaEntries)
    if (!mCompositionTimeDeltaEntries) {
        ALOGE("Cannot allocate composition-time-to-sample table with %llu "
                "entries.", (unsigned long long)numEntries);
        return ERROR_OUT_OF_RANGE;
    }

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

@@ -465,18 +536,33 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size)
        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) {
    uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
    if (allocSize > kMaxTotalSize) {
        ALOGE("Sync sample table size too large.");
        return ERROR_OUT_OF_RANGE;
    }

    mTotalSize += allocSize;
    if (mTotalSize > kMaxTotalSize) {
        ALOGE("Sync sample table size would make sample table too large.\n"
              "    Requested sync sample table size = %llu\n"
              "    Eventual sample table size >= %llu\n"
              "    Allowed sample table size = %llu\n",
              (unsigned long long)allocSize,
              (unsigned long long)mTotalSize,
              (unsigned long long)kMaxTotalSize);
        return ERROR_OUT_OF_RANGE;
    }

    mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
    if (!mSyncSamples)
    if (!mSyncSamples) {
        ALOGE("Cannot allocate sync sample table with %llu entries.",
                (unsigned long long)mNumSyncSamples);
        return ERROR_OUT_OF_RANGE;
    }

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

@@ -544,9 +630,24 @@ void SampleTable::buildSampleEntriesTable() {
        return;
    }

    mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
    if (mTotalSize > kMaxTotalSize) {
        ALOGE("Sample entry table size would make sample table too large.\n"
              "    Requested sample entry table size = %llu\n"
              "    Eventual sample table size >= %llu\n"
              "    Allowed sample table size = %llu\n",
              (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
              (unsigned long long)mTotalSize,
              (unsigned long long)kMaxTotalSize);
        return;
    }

    mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
    if (!mSampleTimeEntries)
    if (!mSampleTimeEntries) {
        ALOGE("Cannot allocate sample entry table with %llu entries.",
                (unsigned long long)mNumSampleSizes);
        return;
    }

    uint32_t sampleIndex = 0;
    uint32_t sampleTime = 0;
+11 −10
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <sys/stat.h>

#include <utility>
#include <vector>

#include "include/ESDS.h"
#include "include/HevcUtils.h"
@@ -1385,24 +1386,24 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
    // reassemble the csd data into its original form
    sp<ABuffer> csd0, csd1, csd2;
    if (msg->findBuffer("csd-0", &csd0)) {
        int csd0size = csd0->size();
        if (mime == MEDIA_MIMETYPE_VIDEO_AVC) {
            sp<ABuffer> csd1;
            if (msg->findBuffer("csd-1", &csd1)) {
                char avcc[1024]; // that oughta be enough, right?
                size_t outsize = reassembleAVCC(csd0, csd1, avcc);
                meta->setData(kKeyAVCC, kKeyAVCC, avcc, outsize);
                std::vector<char> avcc(csd0size + csd1->size() + 1024);
                size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
                meta->setData(kKeyAVCC, kKeyAVCC, avcc.data(), outsize);
            }
        } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
            int csd0size = csd0->size();
            char esds[csd0size + 31];
            std::vector<char> esds(csd0size + 31);
            // The written ESDS is actually for an audio stream, but it's enough
            // for transporting the CSD to muxers.
            reassembleESDS(csd0, esds);
            meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds));
            reassembleESDS(csd0, esds.data());
            meta->setData(kKeyESDS, kKeyESDS, esds.data(), esds.size());
        } else if (mime == MEDIA_MIMETYPE_VIDEO_HEVC) {
            uint8_t hvcc[1024]; // that oughta be enough, right?
            size_t outsize = reassembleHVCC(csd0, hvcc, 1024, 4);
            meta->setData(kKeyHVCC, kKeyHVCC, hvcc, outsize);
            std::vector<uint8_t> hvcc(csd0size + 1024);
            size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
            meta->setData(kKeyHVCC, kKeyHVCC, hvcc.data(), outsize);
        } else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
            meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
        } else if (mime == MEDIA_MIMETYPE_AUDIO_OPUS) {
+18 −4
Original line number Diff line number Diff line
@@ -122,6 +122,17 @@ void SoftMP3::initDecoder() {
    mIsFirst = true;
}

void *SoftMP3::memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len) {
    if (len > outHeader->nAllocLen) {
        ALOGE("memset buffer too small: got %u, expected %zu", outHeader->nAllocLen, len);
        android_errorWriteLog(0x534e4554, "29422022");
        notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL);
        mSignalledError = true;
        return NULL;
    }
    return memset(outHeader->pBuffer, c, len);
}

OMX_ERRORTYPE SoftMP3::internalGetParameter(
        OMX_INDEXTYPE index, OMX_PTR params) {
    switch (index) {
@@ -315,7 +326,10 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
                    outHeader->nOffset = 0;
                    outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);

                    memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
                    if (!memsetSafe(outHeader, 0, outHeader->nFilledLen)) {
                        return;
                    }

                }
                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
                mSignalledOutputEos = true;
@@ -327,9 +341,9 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
                // if mIsFirst is true as we may not have a valid
                // mConfig->samplingRate and mConfig->num_channels?
                ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
                memset(outHeader->pBuffer,
                       0,
                       mConfig->outputFrameSize * sizeof(int16_t));
                if (!memsetSafe(outHeader, 0, mConfig->outputFrameSize * sizeof(int16_t))) {
                    return;
                }

                if (inHeader) {
                    mConfig->inputBufferUsedLength = inHeader->nFilledLen;
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ private:

    void initPorts();
    void initDecoder();
    void *memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len);

    DISALLOW_EVIL_CONSTRUCTORS(SoftMP3);
};
+20 −3
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por
        outHeader->nFlags = 0;
        outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
        outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv;
        if (outHeader->nAllocLen >= outHeader->nFilledLen) {
        if (outputBufferSafe(outHeader)) {
            uint8_t *dst = outHeader->pBuffer;
            const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y];
            const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U];
@@ -166,8 +166,6 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por
            size_t srcVStride = mImg->stride[VPX_PLANE_V];
            copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
        } else {
            ALOGE("b/27597103, buffer too small");
            android_errorWriteLog(0x534e4554, "27597103");
            outHeader->nFilledLen = 0;
        }

@@ -197,6 +195,25 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por
    return true;
}

bool SoftVPX::outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader) {
    uint32_t width = outputBufferWidth();
    uint32_t height = outputBufferHeight();
    uint64_t nFilledLen = width;
    nFilledLen *= height;
    if (nFilledLen > UINT32_MAX / 3) {
        ALOGE("b/29421675, nFilledLen overflow %llu w %u h %u",
                (unsigned long long)nFilledLen, width, height);
        android_errorWriteLog(0x534e4554, "29421675");
        return false;
    } else if (outHeader->nAllocLen < outHeader->nFilledLen) {
        ALOGE("b/27597103, buffer too small");
        android_errorWriteLog(0x534e4554, "27597103");
        return false;
    }

    return true;
}

void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
    if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
        return;
Loading