frameworks/av
Révision | d8bd197f4346cacfc8f6b5b2c875db4de4600393 (tree) |
---|---|
l'heure | 2016-09-07 14:46:27 |
Auteur | Chih-Wei Huang <cwhuang@linu...> |
Commiter | Chih-Wei Huang |
Merge tag 'android-6.0.1_r66' into marshmallow-x86
Android 6.0.1 release 66
@@ -237,7 +237,8 @@ void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attribu | ||
237 | 237 | // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it |
238 | 238 | size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ? |
239 | 239 | AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize; |
240 | - utf16_to_utf8(tags.string(), tagSize, attributes->tags); | |
240 | + utf16_to_utf8(tags.string(), tagSize, attributes->tags, | |
241 | + sizeof(attributes->tags) / sizeof(attributes->tags[0])); | |
241 | 242 | } |
242 | 243 | } else { |
243 | 244 | ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values"); |
@@ -1625,7 +1625,9 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { | ||
1625 | 1625 | |
1626 | 1626 | for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { |
1627 | 1627 | sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); |
1628 | - CHECK(mem.get() != NULL); | |
1628 | + if (mem == NULL || mem->pointer() == NULL) { | |
1629 | + return NO_MEMORY; | |
1630 | + } | |
1629 | 1631 | |
1630 | 1632 | BufferInfo info; |
1631 | 1633 | info.mData = NULL; |
@@ -18,6 +18,8 @@ | ||
18 | 18 | //#define LOG_NDEBUG 0 |
19 | 19 | #include <utils/Log.h> |
20 | 20 | |
21 | +#include <limits> | |
22 | + | |
21 | 23 | #include "include/SampleTable.h" |
22 | 24 | #include "include/SampleIterator.h" |
23 | 25 |
@@ -27,11 +29,6 @@ | ||
27 | 29 | #include <media/stagefright/DataSource.h> |
28 | 30 | #include <media/stagefright/Utils.h> |
29 | 31 | |
30 | -/* TODO: remove after being merged into other branches */ | |
31 | -#ifndef UINT32_MAX | |
32 | -#define UINT32_MAX (4294967295U) | |
33 | -#endif | |
34 | - | |
35 | 32 | namespace android { |
36 | 33 | |
37 | 34 | // static |
@@ -45,6 +42,8 @@ const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2'); | ||
45 | 42 | |
46 | 43 | //////////////////////////////////////////////////////////////////////////////// |
47 | 44 | |
45 | +const off64_t kMaxOffset = std::numeric_limits<off64_t>::max(); | |
46 | + | |
48 | 47 | struct SampleTable::CompositionDeltaLookup { |
49 | 48 | CompositionDeltaLookup(); |
50 | 49 |
@@ -123,7 +122,7 @@ SampleTable::SampleTable(const sp<DataSource> &source) | ||
123 | 122 | mNumSampleSizes(0), |
124 | 123 | mHasTimeToSample(false), |
125 | 124 | mTimeToSampleCount(0), |
126 | - mTimeToSample(), | |
125 | + mTimeToSample(NULL), | |
127 | 126 | mSampleTimeEntries(NULL), |
128 | 127 | mCompositionTimeDeltaEntries(NULL), |
129 | 128 | mNumCompositionTimeDeltaEntries(0), |
@@ -132,7 +131,8 @@ SampleTable::SampleTable(const sp<DataSource> &source) | ||
132 | 131 | mNumSyncSamples(0), |
133 | 132 | mSyncSamples(NULL), |
134 | 133 | mLastSyncSampleIndex(0), |
135 | - mSampleToChunkEntries(NULL) { | |
134 | + mSampleToChunkEntries(NULL), | |
135 | + mTotalSize(0) { | |
136 | 136 | mSampleIterator = new SampleIterator(this); |
137 | 137 | } |
138 | 138 |
@@ -143,6 +143,9 @@ SampleTable::~SampleTable() { | ||
143 | 143 | delete[] mSyncSamples; |
144 | 144 | mSyncSamples = NULL; |
145 | 145 | |
146 | + delete[] mTimeToSample; | |
147 | + mTimeToSample = NULL; | |
148 | + | |
146 | 149 | delete mCompositionDeltaLookup; |
147 | 150 | mCompositionDeltaLookup = NULL; |
148 | 151 |
@@ -229,27 +232,63 @@ status_t SampleTable::setSampleToChunkParams( | ||
229 | 232 | |
230 | 233 | mNumSampleToChunkOffsets = U32_AT(&header[4]); |
231 | 234 | |
232 | - if (data_size < 8 + mNumSampleToChunkOffsets * 12) { | |
235 | + if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) { | |
233 | 236 | return ERROR_MALFORMED; |
234 | 237 | } |
235 | 238 | |
236 | - if (SIZE_MAX / sizeof(SampleToChunkEntry) <= (size_t)mNumSampleToChunkOffsets) | |
239 | + if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <= | |
240 | + (uint64_t)mNumSampleToChunkOffsets) { | |
241 | + ALOGE("Sample-to-chunk table size too large."); | |
242 | + return ERROR_OUT_OF_RANGE; | |
243 | + } | |
244 | + | |
245 | + mTotalSize += (uint64_t)mNumSampleToChunkOffsets * | |
246 | + sizeof(SampleToChunkEntry); | |
247 | + if (mTotalSize > kMaxTotalSize) { | |
248 | + ALOGE("Sample-to-chunk table size would make sample table too large.\n" | |
249 | + " Requested sample-to-chunk table size = %llu\n" | |
250 | + " Eventual sample table size >= %llu\n" | |
251 | + " Allowed sample table size = %llu\n", | |
252 | + (unsigned long long)mNumSampleToChunkOffsets * | |
253 | + sizeof(SampleToChunkEntry), | |
254 | + (unsigned long long)mTotalSize, | |
255 | + (unsigned long long)kMaxTotalSize); | |
237 | 256 | return ERROR_OUT_OF_RANGE; |
257 | + } | |
238 | 258 | |
239 | 259 | mSampleToChunkEntries = |
240 | 260 | new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets]; |
241 | - if (!mSampleToChunkEntries) | |
261 | + if (!mSampleToChunkEntries) { | |
262 | + ALOGE("Cannot allocate sample-to-chunk table with %llu entries.", | |
263 | + (unsigned long long)mNumSampleToChunkOffsets); | |
242 | 264 | return ERROR_OUT_OF_RANGE; |
265 | + } | |
266 | + | |
267 | + if (mNumSampleToChunkOffsets == 0) { | |
268 | + return OK; | |
269 | + } | |
270 | + | |
271 | + if ((off64_t)(kMaxOffset - 8 - | |
272 | + ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry))) | |
273 | + < mSampleToChunkOffset) { | |
274 | + return ERROR_MALFORMED; | |
275 | + } | |
243 | 276 | |
244 | 277 | for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { |
245 | - uint8_t buffer[12]; | |
278 | + uint8_t buffer[sizeof(SampleToChunkEntry)]; | |
279 | + | |
246 | 280 | if (mDataSource->readAt( |
247 | - mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer)) | |
281 | + mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry), | |
282 | + buffer, | |
283 | + sizeof(buffer)) | |
248 | 284 | != (ssize_t)sizeof(buffer)) { |
249 | 285 | return ERROR_IO; |
250 | 286 | } |
251 | - | |
252 | - CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec. | |
287 | + // chunk index is 1 based in the spec. | |
288 | + if (U32_AT(buffer) < 1) { | |
289 | + ALOGE("b/23534160"); | |
290 | + return ERROR_OUT_OF_RANGE; | |
291 | + } | |
253 | 292 | |
254 | 293 | // We want the chunk index to be 0-based. |
255 | 294 | mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1; |
@@ -341,29 +380,48 @@ status_t SampleTable::setTimeToSampleParams( | ||
341 | 380 | } |
342 | 381 | |
343 | 382 | mTimeToSampleCount = U32_AT(&header[4]); |
344 | - if ((uint64_t)mTimeToSampleCount > | |
345 | - (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) { | |
383 | + if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) { | |
346 | 384 | // Choose this bound because |
347 | 385 | // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one |
348 | 386 | // time-to-sample entry in the time-to-sample table. |
349 | 387 | // 2) mTimeToSampleCount is the number of entries of the time-to-sample |
350 | 388 | // table. |
351 | 389 | // 3) We hope that the table size does not exceed UINT32_MAX. |
352 | - ALOGE(" Error: Time-to-sample table size too large."); | |
353 | - | |
390 | + ALOGE("Time-to-sample table size too large."); | |
354 | 391 | return ERROR_OUT_OF_RANGE; |
355 | 392 | } |
356 | 393 | |
357 | 394 | // Note: At this point, we know that mTimeToSampleCount * 2 will not |
358 | 395 | // overflow because of the above condition. |
359 | - if (!mDataSource->getVector(data_offset + 8, &mTimeToSample, | |
360 | - mTimeToSampleCount * 2)) { | |
361 | - ALOGE(" Error: Incomplete data read for time-to-sample table."); | |
396 | + | |
397 | + uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); | |
398 | + mTotalSize += allocSize; | |
399 | + if (mTotalSize > kMaxTotalSize) { | |
400 | + ALOGE("Time-to-sample table size would make sample table too large.\n" | |
401 | + " Requested time-to-sample table size = %llu\n" | |
402 | + " Eventual sample table size >= %llu\n" | |
403 | + " Allowed sample table size = %llu\n", | |
404 | + (unsigned long long)allocSize, | |
405 | + (unsigned long long)mTotalSize, | |
406 | + (unsigned long long)kMaxTotalSize); | |
407 | + return ERROR_OUT_OF_RANGE; | |
408 | + } | |
409 | + | |
410 | + mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2]; | |
411 | + if (!mTimeToSample) { | |
412 | + ALOGE("Cannot allocate time-to-sample table with %llu entries.", | |
413 | + (unsigned long long)mTimeToSampleCount); | |
414 | + return ERROR_OUT_OF_RANGE; | |
415 | + } | |
416 | + | |
417 | + if (mDataSource->readAt(data_offset + 8, mTimeToSample, | |
418 | + (size_t)allocSize) < (ssize_t)allocSize) { | |
419 | + ALOGE("Incomplete data read for time-to-sample table."); | |
362 | 420 | return ERROR_IO; |
363 | 421 | } |
364 | 422 | |
365 | - for (size_t i = 0; i < mTimeToSample.size(); ++i) { | |
366 | - mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]); | |
423 | + for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) { | |
424 | + mTimeToSample[i] = ntohl(mTimeToSample[i]); | |
367 | 425 | } |
368 | 426 | |
369 | 427 | mHasTimeToSample = true; |
@@ -398,17 +456,32 @@ status_t SampleTable::setCompositionTimeToSampleParams( | ||
398 | 456 | |
399 | 457 | mNumCompositionTimeDeltaEntries = numEntries; |
400 | 458 | uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t); |
401 | - if (allocSize > UINT32_MAX) { | |
459 | + if (allocSize > kMaxTotalSize) { | |
460 | + ALOGE("Composition-time-to-sample table size too large."); | |
461 | + return ERROR_OUT_OF_RANGE; | |
462 | + } | |
463 | + | |
464 | + mTotalSize += allocSize; | |
465 | + if (mTotalSize > kMaxTotalSize) { | |
466 | + ALOGE("Composition-time-to-sample table would make sample table too large.\n" | |
467 | + " Requested composition-time-to-sample table size = %llu\n" | |
468 | + " Eventual sample table size >= %llu\n" | |
469 | + " Allowed sample table size = %llu\n", | |
470 | + (unsigned long long)allocSize, | |
471 | + (unsigned long long)mTotalSize, | |
472 | + (unsigned long long)kMaxTotalSize); | |
402 | 473 | return ERROR_OUT_OF_RANGE; |
403 | 474 | } |
404 | 475 | |
405 | 476 | mCompositionTimeDeltaEntries = new (std::nothrow) uint32_t[2 * numEntries]; |
406 | - if (!mCompositionTimeDeltaEntries) | |
477 | + if (!mCompositionTimeDeltaEntries) { | |
478 | + ALOGE("Cannot allocate composition-time-to-sample table with %llu " | |
479 | + "entries.", (unsigned long long)numEntries); | |
407 | 480 | return ERROR_OUT_OF_RANGE; |
481 | + } | |
408 | 482 | |
409 | - if (mDataSource->readAt( | |
410 | - data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8) | |
411 | - < (ssize_t)numEntries * 8) { | |
483 | + if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries, | |
484 | + (size_t)allocSize) < (ssize_t)allocSize) { | |
412 | 485 | delete[] mCompositionTimeDeltaEntries; |
413 | 486 | mCompositionTimeDeltaEntries = NULL; |
414 | 487 |
@@ -449,18 +522,33 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) | ||
449 | 522 | ALOGV("Table of sync samples is empty or has only a single entry!"); |
450 | 523 | } |
451 | 524 | |
452 | - uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t); | |
453 | - if (allocSize > SIZE_MAX) { | |
525 | + uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t); | |
526 | + if (allocSize > kMaxTotalSize) { | |
527 | + ALOGE("Sync sample table size too large."); | |
528 | + return ERROR_OUT_OF_RANGE; | |
529 | + } | |
530 | + | |
531 | + mTotalSize += allocSize; | |
532 | + if (mTotalSize > kMaxTotalSize) { | |
533 | + ALOGE("Sync sample table size would make sample table too large.\n" | |
534 | + " Requested sync sample table size = %llu\n" | |
535 | + " Eventual sample table size >= %llu\n" | |
536 | + " Allowed sample table size = %llu\n", | |
537 | + (unsigned long long)allocSize, | |
538 | + (unsigned long long)mTotalSize, | |
539 | + (unsigned long long)kMaxTotalSize); | |
454 | 540 | return ERROR_OUT_OF_RANGE; |
455 | 541 | } |
456 | 542 | |
457 | 543 | mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples]; |
458 | - if (!mSyncSamples) | |
544 | + if (!mSyncSamples) { | |
545 | + ALOGE("Cannot allocate sync sample table with %llu entries.", | |
546 | + (unsigned long long)mNumSyncSamples); | |
459 | 547 | return ERROR_OUT_OF_RANGE; |
548 | + } | |
460 | 549 | |
461 | - size_t size = mNumSyncSamples * sizeof(uint32_t); | |
462 | - if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size) | |
463 | - != (ssize_t)size) { | |
550 | + if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, | |
551 | + (size_t)allocSize) != (ssize_t)allocSize) { | |
464 | 552 | return ERROR_IO; |
465 | 553 | } |
466 | 554 |
@@ -525,9 +613,24 @@ void SampleTable::buildSampleEntriesTable() { | ||
525 | 613 | return; |
526 | 614 | } |
527 | 615 | |
616 | + mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry); | |
617 | + if (mTotalSize > kMaxTotalSize) { | |
618 | + ALOGE("Sample entry table size would make sample table too large.\n" | |
619 | + " Requested sample entry table size = %llu\n" | |
620 | + " Eventual sample table size >= %llu\n" | |
621 | + " Allowed sample table size = %llu\n", | |
622 | + (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry), | |
623 | + (unsigned long long)mTotalSize, | |
624 | + (unsigned long long)kMaxTotalSize); | |
625 | + return; | |
626 | + } | |
627 | + | |
528 | 628 | mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes]; |
529 | - if (!mSampleTimeEntries) | |
629 | + if (!mSampleTimeEntries) { | |
630 | + ALOGE("Cannot allocate sample entry table with %llu entries.", | |
631 | + (unsigned long long)mNumSampleSizes); | |
530 | 632 | return; |
633 | + } | |
531 | 634 | |
532 | 635 | uint32_t sampleIndex = 0; |
533 | 636 | uint32_t sampleTime = 0; |
@@ -671,20 +671,30 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) { | ||
671 | 671 | // reassemble the csd data into its original form |
672 | 672 | sp<ABuffer> csd0; |
673 | 673 | if (msg->findBuffer("csd-0", &csd0)) { |
674 | + int csd0size = csd0->size(); | |
674 | 675 | if (mime == MEDIA_MIMETYPE_VIDEO_AVC) { |
675 | 676 | sp<ABuffer> csd1; |
676 | 677 | if (msg->findBuffer("csd-1", &csd1)) { |
677 | - char avcc[1024]; // that oughta be enough, right? | |
678 | - size_t outsize = reassembleAVCC(csd0, csd1, avcc); | |
679 | - meta->setData(kKeyAVCC, kKeyAVCC, avcc, outsize); | |
678 | + Vector<char> avcc; | |
679 | + int avccSize = csd0size + csd1->size() + 1024; | |
680 | + if (avcc.resize(avccSize) < 0) { | |
681 | + ALOGE("error allocating avcc (size %d); abort setting avcc.", avccSize); | |
682 | + } else { | |
683 | + size_t outsize = reassembleAVCC(csd0, csd1, avcc.editArray()); | |
684 | + meta->setData(kKeyAVCC, kKeyAVCC, avcc.array(), outsize); | |
685 | + } | |
680 | 686 | } |
681 | 687 | } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) { |
682 | - int csd0size = csd0->size(); | |
683 | - char esds[csd0size + 31]; | |
684 | - // The written ESDS is actually for an audio stream, but it's enough | |
685 | - // for transporting the CSD to muxers. | |
686 | - reassembleESDS(csd0, esds); | |
687 | - meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds)); | |
688 | + Vector<char> esds; | |
689 | + int esdsSize = csd0size + 31; | |
690 | + if (esds.resize(esdsSize) < 0) { | |
691 | + ALOGE("error allocating esds (size %d); abort setting esds.", esdsSize); | |
692 | + } else { | |
693 | + // The written ESDS is actually for an audio stream, but it's enough | |
694 | + // for transporting the CSD to muxers. | |
695 | + reassembleESDS(csd0, esds.editArray()); | |
696 | + meta->setData(kKeyESDS, kKeyESDS, esds.array(), esds.size()); | |
697 | + } | |
688 | 698 | } |
689 | 699 | } |
690 | 700 |
@@ -120,6 +120,17 @@ void SoftMP3::initDecoder() { | ||
120 | 120 | mIsFirst = true; |
121 | 121 | } |
122 | 122 | |
123 | +void *SoftMP3::memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len) { | |
124 | + if (len > outHeader->nAllocLen) { | |
125 | + ALOGE("memset buffer too small: got %u, expected %zu", outHeader->nAllocLen, len); | |
126 | + android_errorWriteLog(0x534e4554, "29422022"); | |
127 | + notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL); | |
128 | + mSignalledError = true; | |
129 | + return NULL; | |
130 | + } | |
131 | + return memset(outHeader->pBuffer, c, len); | |
132 | +} | |
133 | + | |
123 | 134 | OMX_ERRORTYPE SoftMP3::internalGetParameter( |
124 | 135 | OMX_INDEXTYPE index, OMX_PTR params) { |
125 | 136 | switch (index) { |
@@ -300,7 +311,10 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { | ||
300 | 311 | outHeader->nOffset = 0; |
301 | 312 | outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); |
302 | 313 | |
303 | - memset(outHeader->pBuffer, 0, outHeader->nFilledLen); | |
314 | + if (!memsetSafe(outHeader, 0, outHeader->nFilledLen)) { | |
315 | + return; | |
316 | + } | |
317 | + | |
304 | 318 | } |
305 | 319 | outHeader->nFlags = OMX_BUFFERFLAG_EOS; |
306 | 320 | mSignalledOutputEos = true; |
@@ -312,9 +326,9 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { | ||
312 | 326 | // if mIsFirst is true as we may not have a valid |
313 | 327 | // mConfig->samplingRate and mConfig->num_channels? |
314 | 328 | ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence"); |
315 | - memset(outHeader->pBuffer, | |
316 | - 0, | |
317 | - mConfig->outputFrameSize * sizeof(int16_t)); | |
329 | + if (!memsetSafe(outHeader, 0, mConfig->outputFrameSize * sizeof(int16_t))) { | |
330 | + return; | |
331 | + } | |
318 | 332 | |
319 | 333 | if (inHeader) { |
320 | 334 | mConfig->inputBufferUsedLength = inHeader->nFilledLen; |
@@ -72,6 +72,7 @@ private: | ||
72 | 72 | |
73 | 73 | void initPorts(); |
74 | 74 | void initDecoder(); |
75 | + void *memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len); | |
75 | 76 | |
76 | 77 | DISALLOW_EVIL_CONSTRUCTORS(SoftMP3); |
77 | 78 | }; |
@@ -149,7 +149,7 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por | ||
149 | 149 | outHeader->nFlags = 0; |
150 | 150 | outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2; |
151 | 151 | outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv; |
152 | - if (outHeader->nAllocLen >= outHeader->nFilledLen) { | |
152 | + if (outputBufferSafe(outHeader)) { | |
153 | 153 | uint8_t *dst = outHeader->pBuffer; |
154 | 154 | const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y]; |
155 | 155 | const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U]; |
@@ -159,8 +159,6 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por | ||
159 | 159 | size_t srcVStride = mImg->stride[VPX_PLANE_V]; |
160 | 160 | copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); |
161 | 161 | } else { |
162 | - ALOGE("b/27597103, buffer too small"); | |
163 | - android_errorWriteLog(0x534e4554, "27597103"); | |
164 | 162 | outHeader->nFilledLen = 0; |
165 | 163 | } |
166 | 164 |
@@ -190,6 +188,25 @@ bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *por | ||
190 | 188 | return true; |
191 | 189 | } |
192 | 190 | |
191 | +bool SoftVPX::outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader) { | |
192 | + uint32_t width = outputBufferWidth(); | |
193 | + uint32_t height = outputBufferHeight(); | |
194 | + uint64_t nFilledLen = width; | |
195 | + nFilledLen *= height; | |
196 | + if (nFilledLen > UINT32_MAX / 3) { | |
197 | + ALOGE("b/29421675, nFilledLen overflow %llu w %u h %u", | |
198 | + (unsigned long long)nFilledLen, width, height); | |
199 | + android_errorWriteLog(0x534e4554, "29421675"); | |
200 | + return false; | |
201 | + } else if (outHeader->nAllocLen < outHeader->nFilledLen) { | |
202 | + ALOGE("b/27597103, buffer too small"); | |
203 | + android_errorWriteLog(0x534e4554, "27597103"); | |
204 | + return false; | |
205 | + } | |
206 | + | |
207 | + return true; | |
208 | +} | |
209 | + | |
193 | 210 | void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { |
194 | 211 | if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) { |
195 | 212 | return; |
@@ -66,6 +66,7 @@ private: | ||
66 | 66 | status_t initDecoder(); |
67 | 67 | status_t destroyDecoder(); |
68 | 68 | bool outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset); |
69 | + bool outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader); | |
69 | 70 | |
70 | 71 | DISALLOW_EVIL_CONSTRUCTORS(SoftVPX); |
71 | 72 | }; |
@@ -24,7 +24,6 @@ | ||
24 | 24 | #include <media/stagefright/MediaErrors.h> |
25 | 25 | #include <utils/RefBase.h> |
26 | 26 | #include <utils/threads.h> |
27 | -#include <utils/Vector.h> | |
28 | 27 | |
29 | 28 | namespace android { |
30 | 29 |
@@ -96,6 +95,9 @@ private: | ||
96 | 95 | static const uint32_t kSampleSizeType32; |
97 | 96 | static const uint32_t kSampleSizeTypeCompact; |
98 | 97 | |
98 | + // Limit the total size of all internal tables to 200MiB. | |
99 | + static const size_t kMaxTotalSize = 200 * (1 << 20); | |
100 | + | |
99 | 101 | sp<DataSource> mDataSource; |
100 | 102 | Mutex mLock; |
101 | 103 |
@@ -113,7 +115,7 @@ private: | ||
113 | 115 | |
114 | 116 | bool mHasTimeToSample; |
115 | 117 | uint32_t mTimeToSampleCount; |
116 | - Vector<uint32_t> mTimeToSample; | |
118 | + uint32_t* mTimeToSample; | |
117 | 119 | |
118 | 120 | struct SampleTimeEntry { |
119 | 121 | uint32_t mSampleIndex; |
@@ -139,6 +141,9 @@ private: | ||
139 | 141 | }; |
140 | 142 | SampleToChunkEntry *mSampleToChunkEntries; |
141 | 143 | |
144 | + // Approximate size of all tables combined. | |
145 | + uint64_t mTotalSize; | |
146 | + | |
142 | 147 | friend struct SampleIterator; |
143 | 148 | |
144 | 149 | // normally we don't round |
@@ -469,6 +469,13 @@ void SimpleSoftOMXComponent::onPortEnable(OMX_U32 portIndex, bool enable) { | ||
469 | 469 | CHECK_EQ((int)port->mTransition, (int)PortInfo::NONE); |
470 | 470 | CHECK(port->mDef.bEnabled == !enable); |
471 | 471 | |
472 | + if (port->mDef.eDir != OMX_DirOutput) { | |
473 | + ALOGE("Port enable/disable allowed only on output ports."); | |
474 | + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); | |
475 | + android_errorWriteLog(0x534e4554, "29421804"); | |
476 | + return; | |
477 | + } | |
478 | + | |
472 | 479 | if (!enable) { |
473 | 480 | port->mDef.bEnabled = OMX_FALSE; |
474 | 481 | port->mTransition = PortInfo::DISABLING; |
@@ -17,6 +17,7 @@ | ||
17 | 17 | //#define LOG_NDEBUG 0 |
18 | 18 | #define LOG_TAG "ASessionDescription" |
19 | 19 | #include <utils/Log.h> |
20 | +#include <cutils/log.h> | |
20 | 21 | |
21 | 22 | #include "ASessionDescription.h" |
22 | 23 |
@@ -211,12 +212,12 @@ void ASessionDescription::getFormatType( | ||
211 | 212 | |
212 | 213 | *PT = x; |
213 | 214 | |
214 | - char key[20]; | |
215 | - sprintf(key, "a=rtpmap:%lu", x); | |
215 | + char key[32]; | |
216 | + snprintf(key, sizeof(key), "a=rtpmap:%lu", x); | |
216 | 217 | |
217 | 218 | CHECK(findAttribute(index, key, desc)); |
218 | 219 | |
219 | - sprintf(key, "a=fmtp:%lu", x); | |
220 | + snprintf(key, sizeof(key), "a=fmtp:%lu", x); | |
220 | 221 | if (!findAttribute(index, key, params)) { |
221 | 222 | params->clear(); |
222 | 223 | } |
@@ -228,8 +229,11 @@ bool ASessionDescription::getDimensions( | ||
228 | 229 | *width = 0; |
229 | 230 | *height = 0; |
230 | 231 | |
231 | - char key[20]; | |
232 | - sprintf(key, "a=framesize:%lu", PT); | |
232 | + char key[33]; | |
233 | + snprintf(key, sizeof(key), "a=framesize:%lu", PT); | |
234 | + if (PT > 9999999) { | |
235 | + android_errorWriteLog(0x534e4554, "25747670"); | |
236 | + } | |
233 | 237 | AString value; |
234 | 238 | if (!findAttribute(index, key, &value)) { |
235 | 239 | return false; |