Merge "SoftMP3: memset safely" into mnc-dev
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 56521a2..20e292a 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -237,7 +237,8 @@
// copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
- utf16_to_utf8(tags.string(), tagSize, attributes->tags);
+ utf16_to_utf8(tags.string(), tagSize, attributes->tags,
+ sizeof(attributes->tags) / sizeof(attributes->tags[0]));
}
} else {
ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4618e21..7e15e18 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1622,7 +1622,9 @@
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
- CHECK(mem.get() != NULL);
+ if (mem == NULL || mem->pointer() == NULL) {
+ return NO_MEMORY;
+ }
BufferInfo info;
info.mData = NULL;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 94ed2bf..11e49c8 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -123,7 +123,7 @@
mNumSampleSizes(0),
mHasTimeToSample(false),
mTimeToSampleCount(0),
- mTimeToSample(),
+ mTimeToSample(NULL),
mSampleTimeEntries(NULL),
mCompositionTimeDeltaEntries(NULL),
mNumCompositionTimeDeltaEntries(0),
@@ -132,7 +132,8 @@
mNumSyncSamples(0),
mSyncSamples(NULL),
mLastSyncSampleIndex(0),
- mSampleToChunkEntries(NULL) {
+ mSampleToChunkEntries(NULL),
+ mTotalSize(0) {
mSampleIterator = new SampleIterator(this);
}
@@ -143,6 +144,9 @@
delete[] mSyncSamples;
mSyncSamples = NULL;
+ delete[] mTimeToSample;
+ mTimeToSample = NULL;
+
delete mCompositionDeltaLookup;
mCompositionDeltaLookup = NULL;
@@ -233,13 +237,43 @@
return ERROR_MALFORMED;
}
- if (SIZE_MAX / sizeof(SampleToChunkEntry) <= (size_t)mNumSampleToChunkOffsets)
+ if ((uint64_t)SIZE_MAX / 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;
+ }
+
+ if (mNumSampleToChunkOffsets == 0) {
+ return OK;
+ }
+
+ if ((off64_t)(SIZE_MAX - 8 -
+ ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
+ < mSampleToChunkOffset) {
+ return ERROR_MALFORMED;
+ }
for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
uint8_t buffer[12];
@@ -248,8 +282,11 @@
!= (ssize_t)sizeof(buffer)) {
return ERROR_IO;
}
-
- CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec.
+ // chunk index is 1 based in the spec.
+ if (U32_AT(buffer) < 1) {
+ ALOGE("b/23534160");
+ return ERROR_OUT_OF_RANGE;
+ }
// We want the chunk index to be 0-based.
mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
@@ -350,20 +387,41 @@
// 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;
@@ -398,17 +456,32 @@
mNumCompositionTimeDeltaEntries = numEntries;
uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t);
- if (allocSize > UINT32_MAX) {
+ if (allocSize > SIZE_MAX) {
+ 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) uint32_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;
@@ -449,18 +522,33 @@
ALOGV("Table of sync samples is empty or has only a single entry!");
}
- uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t);
+ uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
if (allocSize > SIZE_MAX) {
+ 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;
}
@@ -528,9 +616,24 @@
return;
}
- mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
- if (!mSampleTimeEntries)
+ 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) {
+ ALOGE("Cannot allocate sample entry table with %llu entries.",
+ (unsigned long long)mNumSampleSizes);
+ return;
+ }
uint32_t sampleIndex = 0;
uint32_t sampleTime = 0;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 7c8d441..296c217 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -671,20 +671,30 @@
// reassemble the csd data into its original form
sp<ABuffer> csd0;
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);
+ Vector<char> avcc;
+ int avccSize = csd0size + csd1->size() + 1024;
+ if (avcc.resize(avccSize) < 0) {
+ ALOGE("error allocating avcc (size %d); abort setting avcc.", avccSize);
+ } else {
+ size_t outsize = reassembleAVCC(csd0, csd1, avcc.editArray());
+ meta->setData(kKeyAVCC, kKeyAVCC, avcc.array(), outsize);
+ }
}
} else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
- int csd0size = csd0->size();
- 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));
+ Vector<char> esds;
+ int esdsSize = csd0size + 31;
+ if (esds.resize(esdsSize) < 0) {
+ ALOGE("error allocating esds (size %d); abort setting esds.", esdsSize);
+ } else {
+ // The written ESDS is actually for an audio stream, but it's enough
+ // for transporting the CSD to muxers.
+ reassembleESDS(csd0, esds.editArray());
+ meta->setData(kKeyESDS, kKeyESDS, esds.array(), esds.size());
+ }
}
}
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 02e85a1..912fac2 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -149,7 +149,7 @@
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];
@@ -159,8 +159,6 @@
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;
}
@@ -190,6 +188,25 @@
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;
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h
index 8ccbae2..84cf79c 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.h
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h
@@ -66,6 +66,7 @@
status_t initDecoder();
status_t destroyDecoder();
bool outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset);
+ bool outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader);
DISALLOW_EVIL_CONSTRUCTORS(SoftVPX);
};
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 465f37c..552eef7 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -24,7 +24,6 @@
#include <media/stagefright/MediaErrors.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
-#include <utils/Vector.h>
namespace android {
@@ -96,6 +95,9 @@
static const uint32_t kSampleSizeType32;
static const uint32_t kSampleSizeTypeCompact;
+ // Limit the total size of all internal tables to 200MiB.
+ static const size_t kMaxTotalSize = 200 * (1 << 20);
+
sp<DataSource> mDataSource;
Mutex mLock;
@@ -113,7 +115,7 @@
bool mHasTimeToSample;
uint32_t mTimeToSampleCount;
- Vector<uint32_t> mTimeToSample;
+ uint32_t* mTimeToSample;
struct SampleTimeEntry {
uint32_t mSampleIndex;
@@ -139,6 +141,9 @@
};
SampleToChunkEntry *mSampleToChunkEntries;
+ // Approximate size of all tables combined.
+ uint64_t mTotalSize;
+
friend struct SampleIterator;
// normally we don't round
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 98498e9..47573c3 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ASessionDescription"
#include <utils/Log.h>
+#include <cutils/log.h>
#include "ASessionDescription.h"
@@ -211,12 +212,12 @@
*PT = x;
- char key[20];
- sprintf(key, "a=rtpmap:%lu", x);
+ char key[32];
+ snprintf(key, sizeof(key), "a=rtpmap:%lu", x);
CHECK(findAttribute(index, key, desc));
- sprintf(key, "a=fmtp:%lu", x);
+ snprintf(key, sizeof(key), "a=fmtp:%lu", x);
if (!findAttribute(index, key, params)) {
params->clear();
}
@@ -228,8 +229,11 @@
*width = 0;
*height = 0;
- char key[20];
- sprintf(key, "a=framesize:%lu", PT);
+ char key[33];
+ snprintf(key, sizeof(key), "a=framesize:%lu", PT);
+ if (PT > 9999999) {
+ android_errorWriteLog(0x534e4554, "25747670");
+ }
AString value;
if (!findAttribute(index, key, &value)) {
return false;