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

Commit ec35db99 authored by Dichen Zhang's avatar Dichen Zhang
Browse files

add chunk size as restriction for function parseClearEncryptedSizes()

Without trunksize as restriction, function parseClearEncryptedSized()
can read the rest of file. If the file has a large number of saiz trunk,
large number of bytes will be copied, which can lead to high cost of
CPU time.

Bug: 124777526
Test: please see #3 and #8 in b/124777526: push senc.mp4 to devices's
sdcard, play with photo app, manuly print log. Also need to verify if
Dexter app (b/152531488) not crash.

Change-Id: I87f215cf04c5d002076e145f21c10556773f4bb2
parent 0428fecb
Loading
Loading
Loading
Loading
+34 −9
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ private:
    const Trex *mTrex;
    off64_t mFirstMoofOffset;
    off64_t mCurrentMoofOffset;
    off64_t mCurrentMoofSize;
    off64_t mNextMoofOffset;
    uint32_t mCurrentTime; // in media timescale ticks
    int32_t mLastParsedTrackId;
@@ -165,8 +166,9 @@ private:
    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
    status_t parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags);
    status_t parseSampleEncryption(off64_t offset);
    status_t parseClearEncryptedSizes(off64_t offset, bool isSampleEncryption,
            uint32_t flags, off64_t size);
    status_t parseSampleEncryption(off64_t offset, off64_t size);
    // returns -1 for invalid layer ID
    int32_t parseHEVCLayerId(const uint8_t *data, size_t size);

@@ -4859,6 +4861,7 @@ MPEG4Source::MPEG4Source(
      mTrex(trex),
      mFirstMoofOffset(firstMoofOffset),
      mCurrentMoofOffset(firstMoofOffset),
      mCurrentMoofSize(0),
      mNextMoofOffset(-1),
      mCurrentTime(0),
      mDefaultEncryptedByteBlock(0),
@@ -5109,6 +5112,9 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
        case FOURCC("moof"): {
            off64_t stop_offset = *offset + chunk_size;
            *offset = data_offset;
            if (chunk_type == FOURCC("moof")) {
                mCurrentMoofSize = chunk_data_size;
            }
            while (*offset < stop_offset) {
                status_t err = parseChunk(offset);
                if (err != OK) {
@@ -5197,7 +5203,7 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {

        case FOURCC("senc"): {
            status_t err;
            if ((err = parseSampleEncryption(data_offset)) != OK) {
            if ((err = parseSampleEncryption(data_offset, chunk_data_size)) != OK) {
                return err;
            }
            *offset += chunk_size;
@@ -5390,11 +5396,11 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(

    drmoffset += mCurrentMoofOffset;

    return parseClearEncryptedSizes(drmoffset, false, 0);
    return parseClearEncryptedSizes(drmoffset, false, 0, mCurrentMoofSize);
}

status_t MPEG4Source::parseClearEncryptedSizes(
        off64_t offset, bool isSubsampleEncryption, uint32_t flags) {
        off64_t offset, bool isSampleEncryption, uint32_t flags, off64_t size) {

    int32_t ivlength;
    if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) {
@@ -5408,11 +5414,15 @@ status_t MPEG4Source::parseClearEncryptedSizes(
    }

    uint32_t sampleCount = mCurrentSampleInfoCount;
    if (isSubsampleEncryption) {
    if (isSampleEncryption) {
        if (size < 4) {
            return ERROR_MALFORMED;
        }
        if (!mDataSource->getUInt32(offset, &sampleCount)) {
            return ERROR_IO;
        }
        offset += 4;
        size -= 4;
    }

    // read CencSampleAuxiliaryDataFormats
@@ -5427,14 +5437,18 @@ status_t MPEG4Source::parseClearEncryptedSizes(
        }

        memset(smpl->iv, 0, 16);
        if (size < ivlength) {
            return ERROR_MALFORMED;
        }
        if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) {
            return ERROR_IO;
        }

        offset += ivlength;
        size -= ivlength;

        bool readSubsamples;
        if (isSubsampleEncryption) {
        if (isSampleEncryption) {
            readSubsamples = flags & 2;
        } else {
            int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
@@ -5446,13 +5460,20 @@ status_t MPEG4Source::parseClearEncryptedSizes(

        if (readSubsamples) {
            uint16_t numsubsamples;
            if (size < 2) {
                return ERROR_MALFORMED;
            }
            if (!mDataSource->getUInt16(offset, &numsubsamples)) {
                return ERROR_IO;
            }
            offset += 2;
            size -= 2;
            for (size_t j = 0; j < numsubsamples; j++) {
                uint16_t numclear;
                uint32_t numencrypted;
                if (size < 6) {
                    return ERROR_MALFORMED;
                }
                if (!mDataSource->getUInt16(offset, &numclear)) {
                    return ERROR_IO;
                }
@@ -5461,6 +5482,7 @@ status_t MPEG4Source::parseClearEncryptedSizes(
                    return ERROR_IO;
                }
                offset += 4;
                size -= 6;
                smpl->clearsizes.add(numclear);
                smpl->encryptedsizes.add(numencrypted);
            }
@@ -5473,12 +5495,15 @@ status_t MPEG4Source::parseClearEncryptedSizes(
    return OK;
}

status_t MPEG4Source::parseSampleEncryption(off64_t offset) {
status_t MPEG4Source::parseSampleEncryption(off64_t offset, off64_t chunk_data_size) {
    uint32_t flags;
    if (chunk_data_size < 4) {
        return ERROR_MALFORMED;
    }
    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
        return ERROR_MALFORMED;
    }
    return parseClearEncryptedSizes(offset + 4, true, flags);
    return parseClearEncryptedSizes(offset + 4, true, flags, chunk_data_size - 4);
}

status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {