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
gugelfrei
Dichen Zhang 4 years ago
parent 0428fecb64
commit ec35db991f

@ -113,6 +113,7 @@ private:
const Trex *mTrex; const Trex *mTrex;
off64_t mFirstMoofOffset; off64_t mFirstMoofOffset;
off64_t mCurrentMoofOffset; off64_t mCurrentMoofOffset;
off64_t mCurrentMoofSize;
off64_t mNextMoofOffset; off64_t mNextMoofOffset;
uint32_t mCurrentTime; // in media timescale ticks uint32_t mCurrentTime; // in media timescale ticks
int32_t mLastParsedTrackId; int32_t mLastParsedTrackId;
@ -165,8 +166,9 @@ private:
status_t parseTrackFragmentRun(off64_t offset, off64_t size); status_t parseTrackFragmentRun(off64_t offset, off64_t size);
status_t parseSampleAuxiliaryInformationSizes(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 parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
status_t parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags); status_t parseClearEncryptedSizes(off64_t offset, bool isSampleEncryption,
status_t parseSampleEncryption(off64_t offset); uint32_t flags, off64_t size);
status_t parseSampleEncryption(off64_t offset, off64_t size);
// returns -1 for invalid layer ID // returns -1 for invalid layer ID
int32_t parseHEVCLayerId(const uint8_t *data, size_t size); int32_t parseHEVCLayerId(const uint8_t *data, size_t size);
@ -4859,6 +4861,7 @@ MPEG4Source::MPEG4Source(
mTrex(trex), mTrex(trex),
mFirstMoofOffset(firstMoofOffset), mFirstMoofOffset(firstMoofOffset),
mCurrentMoofOffset(firstMoofOffset), mCurrentMoofOffset(firstMoofOffset),
mCurrentMoofSize(0),
mNextMoofOffset(-1), mNextMoofOffset(-1),
mCurrentTime(0), mCurrentTime(0),
mDefaultEncryptedByteBlock(0), mDefaultEncryptedByteBlock(0),
@ -5109,6 +5112,9 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
case FOURCC("moof"): { case FOURCC("moof"): {
off64_t stop_offset = *offset + chunk_size; off64_t stop_offset = *offset + chunk_size;
*offset = data_offset; *offset = data_offset;
if (chunk_type == FOURCC("moof")) {
mCurrentMoofSize = chunk_data_size;
}
while (*offset < stop_offset) { while (*offset < stop_offset) {
status_t err = parseChunk(offset); status_t err = parseChunk(offset);
if (err != OK) { if (err != OK) {
@ -5197,7 +5203,7 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
case FOURCC("senc"): { case FOURCC("senc"): {
status_t err; status_t err;
if ((err = parseSampleEncryption(data_offset)) != OK) { if ((err = parseSampleEncryption(data_offset, chunk_data_size)) != OK) {
return err; return err;
} }
*offset += chunk_size; *offset += chunk_size;
@ -5390,11 +5396,11 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
drmoffset += mCurrentMoofOffset; drmoffset += mCurrentMoofOffset;
return parseClearEncryptedSizes(drmoffset, false, 0); return parseClearEncryptedSizes(drmoffset, false, 0, mCurrentMoofSize);
} }
status_t MPEG4Source::parseClearEncryptedSizes( 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; int32_t ivlength;
if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) { if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) {
@ -5408,11 +5414,15 @@ status_t MPEG4Source::parseClearEncryptedSizes(
} }
uint32_t sampleCount = mCurrentSampleInfoCount; uint32_t sampleCount = mCurrentSampleInfoCount;
if (isSubsampleEncryption) { if (isSampleEncryption) {
if (size < 4) {
return ERROR_MALFORMED;
}
if (!mDataSource->getUInt32(offset, &sampleCount)) { if (!mDataSource->getUInt32(offset, &sampleCount)) {
return ERROR_IO; return ERROR_IO;
} }
offset += 4; offset += 4;
size -= 4;
} }
// read CencSampleAuxiliaryDataFormats // read CencSampleAuxiliaryDataFormats
@ -5427,14 +5437,18 @@ status_t MPEG4Source::parseClearEncryptedSizes(
} }
memset(smpl->iv, 0, 16); memset(smpl->iv, 0, 16);
if (size < ivlength) {
return ERROR_MALFORMED;
}
if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) { if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) {
return ERROR_IO; return ERROR_IO;
} }
offset += ivlength; offset += ivlength;
size -= ivlength;
bool readSubsamples; bool readSubsamples;
if (isSubsampleEncryption) { if (isSampleEncryption) {
readSubsamples = flags & 2; readSubsamples = flags & 2;
} else { } else {
int32_t smplinfosize = mCurrentDefaultSampleInfoSize; int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
@ -5446,13 +5460,20 @@ status_t MPEG4Source::parseClearEncryptedSizes(
if (readSubsamples) { if (readSubsamples) {
uint16_t numsubsamples; uint16_t numsubsamples;
if (size < 2) {
return ERROR_MALFORMED;
}
if (!mDataSource->getUInt16(offset, &numsubsamples)) { if (!mDataSource->getUInt16(offset, &numsubsamples)) {
return ERROR_IO; return ERROR_IO;
} }
offset += 2; offset += 2;
size -= 2;
for (size_t j = 0; j < numsubsamples; j++) { for (size_t j = 0; j < numsubsamples; j++) {
uint16_t numclear; uint16_t numclear;
uint32_t numencrypted; uint32_t numencrypted;
if (size < 6) {
return ERROR_MALFORMED;
}
if (!mDataSource->getUInt16(offset, &numclear)) { if (!mDataSource->getUInt16(offset, &numclear)) {
return ERROR_IO; return ERROR_IO;
} }
@ -5461,6 +5482,7 @@ status_t MPEG4Source::parseClearEncryptedSizes(
return ERROR_IO; return ERROR_IO;
} }
offset += 4; offset += 4;
size -= 6;
smpl->clearsizes.add(numclear); smpl->clearsizes.add(numclear);
smpl->encryptedsizes.add(numencrypted); smpl->encryptedsizes.add(numencrypted);
} }
@ -5473,12 +5495,15 @@ status_t MPEG4Source::parseClearEncryptedSizes(
return OK; return OK;
} }
status_t MPEG4Source::parseSampleEncryption(off64_t offset) { status_t MPEG4Source::parseSampleEncryption(off64_t offset, off64_t chunk_data_size) {
uint32_t flags; uint32_t flags;
if (chunk_data_size < 4) {
return ERROR_MALFORMED;
}
if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
return ERROR_MALFORMED; 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) { status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {

Loading…
Cancel
Save