summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRockchip2015-10-08 11:18:53 +0800
committerRockchip2015-10-08 11:18:53 +0800
commitf2703036fad96331e7c81f641dc7099539d11e7d (patch)
treed2eb12ec206c9bdeb779e98e72042dfb1d9a7eb7
parentbd613ab09f94fba6a849a594e3755869cec4dfc2 (diff)
stagefright:merge google secure patch bulletin-2015-14
-rw-r--r--include/media/stagefright/ACodec.h1
-rw-r--r--include/media/stagefright/MetaData.h2
-rwxr-xr-x[-rw-r--r--]include/media/stagefright/foundation/AUtils.h23
-rwxr-xr-xmedia/libmedia/IAudioFlinger.cpp46
-rw-r--r--media/libmedia/ICrypto.cpp6
-rwxr-xr-xmedia/libstagefright/ACodec.cpp9
-rw-r--r--media/libstagefright/DRMExtractor.cpp3
-rwxr-xr-xmedia/libstagefright/MPEG4Extractor.cpp123
-rw-r--r--media/libstagefright/MetaData.cpp30
-rw-r--r--media/libstagefright/OMXCodec.cpp3
-rw-r--r--media/libstagefright/OggExtractor.cpp13
-rwxr-xr-xmedia/libstagefright/SampleTable.cpp18
-rw-r--r--media/libstagefright/SkipCutBuffer.cpp7
-rw-r--r--media/libstagefright/Utils.cpp88
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/util.c19
-rw-r--r--media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp8
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp50
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp35
-rw-r--r--media/libstagefright/codecs/on2/dec/SoftVPX.cpp2
-rw-r--r--media/libstagefright/codecs/opus/dec/SoftOpus.cpp14
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp10
-rw-r--r--media/libstagefright/foundation/ABuffer.cpp11
-rwxr-xr-xmedia/libstagefright/id3/ID3.cpp40
-rw-r--r--media/libstagefright/include/SampleTable.h5
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp8
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp5
-rwxr-xr-xservices/audioflinger/AudioFlinger.cpp22
-rw-r--r--services/audioflinger/Threads.cpp5
-rw-r--r--services/audioflinger/Threads.h2
29 files changed, 499 insertions, 109 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 3246638..b37dcf2 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -194,6 +194,7 @@ private:
bool mSentFormat;
bool mIsEncoder;
bool mUseMetadataOnEncoderOutput;
+ bool mFatalError;
bool mShutdownInProgress;
bool mExplicitShutdown;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 138b3ec4..0316688 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -286,7 +286,7 @@ private:
return mSize <= sizeof(u.reservoir);
}
- void allocateStorage(size_t size);
+ void *allocateStorage(size_t size);
void freeStorage();
void *storage() {
diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h
index d7ecf50..a348fa7 100644..100755
--- a/include/media/stagefright/foundation/AUtils.h
+++ b/include/media/stagefright/foundation/AUtils.h
@@ -63,6 +63,29 @@ inline static const T &max(const T &a, const T &b) {
/* T must be integer type, period must be positive */
template<class T>
+void ENSURE_UNSIGNED_TYPE() {
+ T TYPE_MUST_BE_UNSIGNED[(T)-1 < 0 ? -1 : 0] __unused;
+}
+
+// needle is in range [hayStart, hayStart + haySize)
+template<class T, class U>
+inline static bool isInRange(const T &hayStart, const U &haySize, const T &needle) {
+ ENSURE_UNSIGNED_TYPE<U>();
+ return (T)(hayStart + haySize) >= hayStart && needle >= hayStart && (U)(needle - hayStart) < haySize;
+}
+
+// [needleStart, needleStart + needleSize) is in range [hayStart, hayStart + haySize)
+template<class T, class U>
+inline static bool isInRange(
+ const T &hayStart, const U &haySize, const T &needleStart, const U &needleSize) {
+ ENSURE_UNSIGNED_TYPE<U>();
+ return isInRange(hayStart, haySize, needleStart)
+ && (T)(needleStart + needleSize) >= needleStart
+ && (U)(needleStart + needleSize - hayStart) <= haySize;
+}
+
+/* T must be integer type, period must be positive */
+template<class T>
inline static T periodicError(const T &val, const T &period) {
T err = abs(val) % period;
return (err < (period / 2)) ? err : (period - err);
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 346a192..d7ca425 100755
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -83,6 +83,8 @@ enum {
GET_AUDIO_HW_SYNC
};
+#define MAX_ITEMS_PER_LIST 1024
+
class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
@@ -1289,15 +1291,27 @@ status_t BnAudioFlinger::onTransact(
} break;
case LIST_AUDIO_PORTS: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- unsigned int num_ports = data.readInt32();
+ unsigned int numPortsReq = data.readInt32();
+ if (numPortsReq > MAX_ITEMS_PER_LIST) {
+ numPortsReq = MAX_ITEMS_PER_LIST;
+ }
+ unsigned int numPorts = numPortsReq;
struct audio_port *ports =
- (struct audio_port *)calloc(num_ports,
+ (struct audio_port *)calloc(numPortsReq,
sizeof(struct audio_port));
- status_t status = listAudioPorts(&num_ports, ports);
+ if (ports == NULL) {
+ reply->writeInt32(NO_MEMORY);
+ reply->writeInt32(0);
+ return NO_ERROR;
+ }
+ status_t status = listAudioPorts(&numPorts, ports);
reply->writeInt32(status);
+ reply->writeInt32(numPorts);
if (status == NO_ERROR) {
- reply->writeInt32(num_ports);
- reply->write(&ports, num_ports * sizeof(struct audio_port));
+ if (numPortsReq > numPorts) {
+ numPortsReq = numPorts;
+ }
+ reply->write(ports, numPortsReq * sizeof(struct audio_port));
}
free(ports);
return NO_ERROR;
@@ -1336,15 +1350,27 @@ status_t BnAudioFlinger::onTransact(
} break;
case LIST_AUDIO_PATCHES: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- unsigned int num_patches = data.readInt32();
+ unsigned int numPatchesReq = data.readInt32();
+ if (numPatchesReq > MAX_ITEMS_PER_LIST) {
+ numPatchesReq = MAX_ITEMS_PER_LIST;
+ }
+ unsigned int numPatches = numPatchesReq;
struct audio_patch *patches =
- (struct audio_patch *)calloc(num_patches,
+ (struct audio_patch *)calloc(numPatchesReq,
sizeof(struct audio_patch));
- status_t status = listAudioPatches(&num_patches, patches);
+ if (patches == NULL) {
+ reply->writeInt32(NO_MEMORY);
+ reply->writeInt32(0);
+ return NO_ERROR;
+ }
+ status_t status = listAudioPatches(&numPatches, patches);
reply->writeInt32(status);
+ reply->writeInt32(numPatches);
if (status == NO_ERROR) {
- reply->writeInt32(num_patches);
- reply->write(&patches, num_patches * sizeof(struct audio_patch));
+ if (numPatchesReq > numPatches) {
+ numPatchesReq = numPatches;
+ }
+ reply->write(patches, numPatchesReq * sizeof(struct audio_patch));
}
free(patches);
return NO_ERROR;
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index c26c5bf..f7d8bc6 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -257,9 +257,9 @@ status_t BnCrypto::onTransact(
subSamples,
sizeof(CryptoPlugin::SubSample) * numSubSamples);
- void *dstPtr;
+ void *secureBufferId, *dstPtr;
if (secure) {
- dstPtr = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
+ secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
} else {
dstPtr = malloc(totalSize);
}
@@ -272,7 +272,7 @@ status_t BnCrypto::onTransact(
mode,
srcData,
subSamples, numSubSamples,
- dstPtr,
+ secure ? secureBufferId : dstPtr,
&errorDetailMsg);
reply->writeInt32(result);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 506315b..b455f9e 100755
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -408,6 +408,7 @@ ACodec::ACodec()
mSentFormat(false),
mIsEncoder(false),
mUseMetadataOnEncoderOutput(false),
+ mFatalError(false),
mShutdownInProgress(false),
mExplicitShutdown(false),
mEncoderDelay(0),
@@ -962,6 +963,11 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
return NULL;
}
+ if (mFatalError) {
+ ALOGW("not dequeuing from native window due to fatal error");
+ return NULL;
+ }
+
if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
ALOGE("dequeueBuffer failed.");
return NULL;
@@ -3955,6 +3961,9 @@ void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
ALOGW("Invalid OMX error %#x", error);
}
}
+
+ mFatalError = true;
+
notify->setInt32("err", internalError);
notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
notify->post();
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 63cb430..9cb6e86 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -186,7 +186,8 @@ status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
srcOffset += mNALLengthSize;
- if (srcOffset + nalLength > len) {
+ size_t end = srcOffset + nalLength;
+ if (end > len || end < srcOffset) {
if (decryptedDrmBuffer.data) {
delete [] decryptedDrmBuffer.data;
decryptedDrmBuffer.data = NULL;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 33ecdd9..b1c3b31 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -34,6 +34,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -44,6 +45,11 @@
#include <byteswap.h>
#include "include/ID3.h"
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+
namespace android {
static const char mov_mdhd_language_map[][4] = {
@@ -1718,15 +1724,27 @@ mLastTrack->sampleTable->setSampleSize((sample_size>>3)*num_channels);
// each chunk originally prefixed with a 2 byte length will
// have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
// and thus will grow by 2 bytes per chunk.
+ if (max_size > SIZE_MAX - 10 * 2) {
+ ALOGE("max sample size too big: %zu", max_size);
+ return ERROR_MALFORMED;
+ }
mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
} else {
// No size was specified. Pick a conservatively large size.
- int32_t width, height;
- if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
- !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
+ uint32_t width, height;
+ if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
+ !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
ALOGE("No width or height, assuming worst case 1080p");
width = 1920;
height = 1080;
+ } else {
+ // A resolution was specified, check that it's not too big. The values below
+ // were chosen so that the calculations below don't cause overflows, they're
+ // not indicating that resolutions up to 32kx32k are actually supported.
+ if (width > 32768 || height > 32768) {
+ ALOGE("can't support %u x %u video", width, height);
+ return ERROR_MALFORMED;
+ }
}
const char *mime;
@@ -2225,7 +2243,7 @@ mLastTrack->sampleTable->setSampleSize((sample_size>>3)*num_channels);
ALOGV("chunk_data_size = %lld and data_offset = %lld",
chunk_data_size, data_offset);
- if ((chunk_data_size >= SIZE_MAX - 1)) {
+ if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
return ERROR_MALFORMED;
}
sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
@@ -2520,7 +2538,7 @@ status_t MPEG4Extractor::parseTrackHeader(
}
status_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
- if (size < 4) {
+ if (size < 4 || size == SIZE_MAX) {
return ERROR_MALFORMED;
}
@@ -3645,11 +3663,26 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
}
offset += 4;
+ if (entrycount == 0) {
+ return OK;
+ }
+ if (entrycount > UINT32_MAX / 8) {
+ return ERROR_MALFORMED;
+ }
+
if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
- mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
+ uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
+ if (newPtr == NULL) {
+ return NO_MEMORY;
+ }
+ mCurrentSampleInfoOffsets = newPtr;
mCurrentSampleInfoOffsetsAllocSize = entrycount;
}
mCurrentSampleInfoOffsetCount = entrycount;
+
+ if (mCurrentSampleInfoOffsets == NULL) {
+ return OK;
+ }
for (size_t i = 0; i < entrycount; i++) {
if (version == 0) {
@@ -3677,8 +3710,17 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
int ivlength;
CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
+ // only 0, 8 and 16 byte initialization vectors are supported
+ if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
+ ALOGW("unsupported IV length: %d", ivlength);
+ return ERROR_MALFORMED;
+ }
// read CencSampleAuxiliaryDataFormats
for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
+ if (i >= mCurrentSamples.size()) {
+ ALOGW("too few samples");
+ break;
+ }
Sample *smpl = &mCurrentSamples.editItemAt(i);
memset(smpl->iv, 0, 16);
@@ -4166,6 +4208,10 @@ MPEG4_NEXT_SAMPLE:
CHECK(mBuffer == NULL);
return err;
}
+ if (size > mBuffer->size()) {
+ ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
+ return ERROR_BUFFER_TOO_SMALL;
+ }
}
if(mIsHEVC){
ssize_t num_bytes_read = 0;
@@ -4615,6 +4661,11 @@ status_t MPEG4Source::fragmentedRead(
ALOGV("acquire_buffer returned %d", err);
return err;
}
+ if (size > mBuffer->size()) {
+ ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
+ return ERROR_BUFFER_TOO_SMALL;
+ }
+
}
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
@@ -4634,6 +4685,14 @@ status_t MPEG4Source::fragmentedRead(
if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
if (newBuffer) {
+ if (!isInRange((size_t)0u, mBuffer->size(), size)) {
+ mBuffer->release();
+ mBuffer = NULL;
+
+ ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
+ return ERROR_MALFORMED;
+ }
+
ssize_t num_bytes_read =
mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
@@ -4641,7 +4700,7 @@ status_t MPEG4Source::fragmentedRead(
mBuffer->release();
mBuffer = NULL;
- ALOGV("i/o error");
+ ALOGE("i/o error");
return ERROR_IO;
}
@@ -4713,18 +4772,40 @@ status_t MPEG4Source::fragmentedRead(
ssize_t num_bytes_read = 0;
int32_t drm = 0;
bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+ void *data = NULL;
+ bool isMalFormed = false;
if (usesDRM) {
- num_bytes_read =
- mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
+ if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
+ isMalFormed = true;
+ } else {
+ data = mBuffer->data();
+ }
} else {
- num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
+ int32_t max_size;
+ if (mFormat == NULL
+ || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
+ || !isInRange((size_t)0u, (size_t)max_size, size)) {
+ isMalFormed = true;
+ } else {
+ data = mSrcBuffer;
+ }
+ }
+
+ if (isMalFormed || data == NULL) {
+ ALOGE("isMalFormed size %zu", size);
+ if (mBuffer != NULL) {
+ mBuffer->release();
+ mBuffer = NULL;
+ }
+ return ERROR_MALFORMED;
}
+ num_bytes_read = mDataSource->readAt(offset, data, size);
- if (num_bytes_read < (ssize_t)size) {
- mBuffer->release();
- mBuffer = NULL;
-
- ALOGV("i/o error");
+ if (num_bytes_read < (ssize_t)size) {
+ mBuffer->release();
+ mBuffer = NULL;
+
+ ALOGE("i/o error");
return ERROR_IO;
}
@@ -4738,15 +4819,19 @@ status_t MPEG4Source::fragmentedRead(
size_t dstOffset = 0;
while (srcOffset < size) {
- bool isMalFormed = (srcOffset + mNALLengthSize > size);
+
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
size_t nalLength = 0;
if (!isMalFormed) {
nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
srcOffset += mNALLengthSize;
- isMalFormed = srcOffset + nalLength > size;
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
+ || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
+ || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
}
-
- if (isMalFormed) {
+
+ if (isMalFormed) {
+ ALOGE("Video is malformed; nalLength %zu", nalLength);
ALOGE("Video is malformed");
mBuffer->release();
mBuffer = NULL;
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index 74234a6..826fa5b 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -244,8 +244,10 @@ MetaData::typed_data::~typed_data() {
MetaData::typed_data::typed_data(const typed_data &from)
: mType(from.mType),
mSize(0) {
- allocateStorage(from.mSize);
- memcpy(storage(), from.storage(), mSize);
+ void *dst = allocateStorage(from.mSize);
+ if (dst) {
+ memcpy(dst, from.storage(), mSize);
+ }
}
MetaData::typed_data &MetaData::typed_data::operator=(
@@ -253,8 +255,10 @@ MetaData::typed_data &MetaData::typed_data::operator=(
if (this != &from) {
clear();
mType = from.mType;
- allocateStorage(from.mSize);
- memcpy(storage(), from.storage(), mSize);
+ void *dst = allocateStorage(from.mSize);
+ if (dst) {
+ memcpy(dst, from.storage(), mSize);
+ }
}
return *this;
@@ -271,8 +275,10 @@ void MetaData::typed_data::setData(
clear();
mType = type;
- allocateStorage(size);
- memcpy(storage(), data, size);
+ void *dst = allocateStorage(size);
+ if (dst) {
+ memcpy(dst, data, size);
+ }
}
void MetaData::typed_data::getData(
@@ -282,14 +288,18 @@ void MetaData::typed_data::getData(
*data = storage();
}
-void MetaData::typed_data::allocateStorage(size_t size) {
+void* MetaData::typed_data::allocateStorage(size_t size) {
mSize = size;
if (usesReservoir()) {
- return;
+ return &u.reservoir;
}
-
- u.ext_data = malloc(mSize);
+
+ if (u.ext_data == NULL) {
+ ALOGE("Couldn't allocate %zu bytes for item", size);
+ mSize = 0;
+ }
+ return u.ext_data;
}
void MetaData::typed_data::freeStorage() {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 0e88bbd..aea094a 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1806,6 +1806,9 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
def.nBufferCountActual, def.nBufferSize,
portIndex == kPortIndexInput ? "input" : "output");
+ if (def.nBufferSize != 0 && def.nBufferCountActual > SIZE_MAX / def.nBufferSize) {
+ return BAD_VALUE;
+ }
size_t totalSize = def.nBufferCountActual * def.nBufferSize;
mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 30495e1..f502959 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -972,11 +972,12 @@ static void extractAlbumArt(
}
typeLen = U32_AT(&flac[4]);
- if (typeLen + 1 > sizeof(type)) {
+ if (typeLen > sizeof(type) - 1) {
goto exit;
}
- if (flacSize < 8 + typeLen) {
+ // we've already checked above that flacSize >= 8
+ if (flacSize - 8 < typeLen) {
goto exit;
}
@@ -992,13 +993,17 @@ static void extractAlbumArt(
descLen = U32_AT(&flac[8 + typeLen]);
- if (flacSize < 32 + typeLen + descLen) {
+ if (flacSize < 32 ||
+ flacSize - 32 < typeLen ||
+ flacSize - 32 - typeLen < descLen) {
goto exit;
}
dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
- if (flacSize < 32 + typeLen + descLen + dataLen) {
+
+ // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
+ if (flacSize - 32 - typeLen - descLen < dataLen) {
goto exit;
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 9cb301b..5c43cbd 100755
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -27,6 +27,11 @@
#include <media/stagefright/DataSource.h>
#include <media/stagefright/Utils.h>
+/* TODO: remove after being merged into other branches */
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
namespace android {
// static
@@ -357,6 +362,9 @@ status_t SampleTable::setSampleSizeParams(
mDefaultSampleSize = U32_AT(&header[4]);
mNumSampleSizes = U32_AT(&header[8]);
+ if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
+ return ERROR_MALFORMED;
+ }
if (type == kSampleSizeType32) {
mSampleSizeFieldSize = 32;
@@ -409,7 +417,7 @@ status_t SampleTable::setTimeToSampleParams(
mTimeToSampleCount = U32_AT(&header[4]);
- uint64_t allocSize = mTimeToSampleCount * 2 * (uint64_t)sizeof(uint32_t);
+ uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
if (allocSize > SIZE_MAX) {
return ERROR_OUT_OF_RANGE;
@@ -507,7 +515,7 @@ status_t SampleTable::setComposTimeOffParams(
if(!mComposTimeOffset)
return ERROR_OUT_OF_RANGE;
- size_t size = sizeof(uint32_t) * mComposTimeOffsetCount * 2;
+ uint64_t size = (uint64_t) mComposTimeOffsetCount * 2*sizeof(uint32_t);
if (mDataSource->readAt(
data_offset + 8, mComposTimeOffset, size) < (ssize_t)size) {
return ERROR_IO;
@@ -614,7 +622,7 @@ int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
void SampleTable::buildSampleEntriesTable() {
Mutex::Autolock autoLock(mLock);
- if (mSampleTimeEntries != NULL) {
+ if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
return;
}
@@ -659,6 +667,10 @@ status_t SampleTable::findSampleAtTime(
uint32_t *sample_index, uint32_t flags) {
buildSampleEntriesTable();
+ if (mSampleTimeEntries == NULL) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
uint32_t left = 0;
uint32_t right_plus_one = mNumSampleSizes;
while (left < right_plus_one) {
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
index e2e6d79..1da1e5e 100644
--- a/media/libstagefright/SkipCutBuffer.cpp
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -25,6 +25,13 @@
namespace android {
SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut) {
+
+ if (skip < 0 || cut < 0 || cut > 64 * 1024) {
+ ALOGW("out of range skip/cut: %d/%d, using passthrough instead", skip, cut);
+ skip = 0;
+ cut = 0;
+ }
+
mFrontPadding = mSkip = skip;
mBackPadding = cut;
mWriteHead = 0;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 25afc5b..d86be6e 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -70,6 +70,23 @@ uint64_t hton64(uint64_t x) {
return ((uint64_t)htonl(x & 0xffffffff) << 32) | htonl(x >> 32);
}
+static status_t copyNALUToABuffer(sp<ABuffer> *buffer, const uint8_t *ptr, size_t length) {
+ if (((*buffer)->size() + 4 + length) > ((*buffer)->capacity() - (*buffer)->offset())) {
+ sp<ABuffer> tmpBuffer = new (std::nothrow) ABuffer((*buffer)->size() + 4 + length + 1024);
+ if (tmpBuffer.get() == NULL || tmpBuffer->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(tmpBuffer->data(), (*buffer)->data(), (*buffer)->size());
+ tmpBuffer->setRange(0, (*buffer)->size());
+ (*buffer) = tmpBuffer;
+ }
+
+ memcpy((*buffer)->data() + (*buffer)->size(), "\x00\x00\x00\x01", 4);
+ memcpy((*buffer)->data() + (*buffer)->size() + 4, ptr, length);
+ (*buffer)->setRange((*buffer)->offset(), (*buffer)->size() + 4 + length);
+ return OK;
+}
+
status_t convertMetaDataToMessage(
const sp<MetaData> &meta, sp<AMessage> *format) {
format->clear();
@@ -199,7 +216,10 @@ status_t convertMetaDataToMessage(
ptr += 6;
size -= 6;
- sp<ABuffer> buffer = new ABuffer(1024);
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(1024);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
buffer->setRange(0, 0);
for (size_t i = 0; i < numSeqParameterSets; ++i) {
@@ -209,11 +229,13 @@ status_t convertMetaDataToMessage(
ptr += 2;
size -= 2;
- CHECK(size >= length);
-
- memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
- memcpy(buffer->data() + buffer->size() + 4, ptr, length);
- buffer->setRange(0, buffer->size() + 4 + length);
+ if (size < length) {
+ return BAD_VALUE;
+ }
+ status_t err = copyNALUToABuffer(&buffer, ptr, length);
+ if (err != OK) {
+ return err;
+ }
ptr += length;
size -= length;
@@ -224,7 +246,10 @@ status_t convertMetaDataToMessage(
msg->setBuffer("csd-0", buffer);
- buffer = new ABuffer(1024);
+ buffer = new (std::nothrow) ABuffer(1024);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
buffer->setRange(0, 0);
CHECK(size >= 1);
@@ -239,11 +264,13 @@ status_t convertMetaDataToMessage(
ptr += 2;
size -= 2;
- CHECK(size >= length);
-
- memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
- memcpy(buffer->data() + buffer->size() + 4, ptr, length);
- buffer->setRange(0, buffer->size() + 4 + length);
+ if (size < length) {
+ return BAD_VALUE;
+ }
+ status_t err = copyNALUToABuffer(&buffer, ptr, length);
+ if (err != OK) {
+ return err;
+ }
ptr += length;
size -= length;
@@ -268,7 +295,10 @@ status_t convertMetaDataToMessage(
size -= 1;
size_t j = 0, i = 0;
- sp<ABuffer> buffer = new ABuffer(1024);
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(1024);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
buffer->setRange(0, 0);
for (i = 0; i < numofArrays; i++) {
@@ -288,11 +318,13 @@ status_t convertMetaDataToMessage(
ptr += 2;
size -= 2;
- CHECK(size >= length);
-
- memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
- memcpy(buffer->data() + buffer->size() + 4, ptr, length);
- buffer->setRange(0, buffer->size() + 4 + length);
+ if (size < length) {
+ return BAD_VALUE;
+ }
+ status_t err = copyNALUToABuffer(&buffer, ptr, length);
+ if (err != OK) {
+ return err;
+ }
ptr += length;
size -= length;
@@ -311,7 +343,10 @@ status_t convertMetaDataToMessage(
esds.getCodecSpecificInfo(
&codec_specific_data, &codec_specific_data_size);
- sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(codec_specific_data_size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
memcpy(buffer->data(), codec_specific_data,
codec_specific_data_size);
@@ -320,7 +355,10 @@ status_t convertMetaDataToMessage(
buffer->meta()->setInt64("timeUs", 0);
msg->setBuffer("csd-0", buffer);
} else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
- sp<ABuffer> buffer = new ABuffer(size);
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
memcpy(buffer->data(), data, size);
buffer->meta()->setInt32("csd", true);
@@ -331,14 +369,20 @@ status_t convertMetaDataToMessage(
return -EINVAL;
}
- buffer = new ABuffer(size);
+ buffer = new (std::nothrow) ABuffer(size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
memcpy(buffer->data(), data, size);
buffer->meta()->setInt32("csd", true);
buffer->meta()->setInt64("timeUs", 0);
msg->setBuffer("csd-1", buffer);
} else if (meta->findData(kKeyOpusHeader, &type, &data, &size)) {
- sp<ABuffer> buffer = new ABuffer(size);
+ sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
memcpy(buffer->data(), data, size);
buffer->meta()->setInt32("csd", true);
diff --git a/media/libstagefright/codecs/amrwbenc/src/util.c b/media/libstagefright/codecs/amrwbenc/src/util.c
index 76ab1b1..333140d 100644
--- a/media/libstagefright/codecs/amrwbenc/src/util.c
+++ b/media/libstagefright/codecs/amrwbenc/src/util.c
@@ -35,9 +35,10 @@ void Set_zero(
)
{
Word32 num = (Word32)L;
- do{
+ while (num > 0) {
*x++ = 0;
- }while(--num !=0);
+ --num;
+ }
}
@@ -54,20 +55,22 @@ void Copy(
)
{
Word32 temp1,temp2,num;
+ if (L <= 0) {
+ return;
+ }
if(L&1)
{
temp1 = *x++;
*y++ = temp1;
}
num = (Word32)(L>>1);
- temp1 = *x++;
- temp2 = *x++;
- do{
- *y++ = temp1;
- *y++ = temp2;
+ while (num > 0) {
temp1 = *x++;
temp2 = *x++;
- }while(--num!=0);
+ *y++ = temp1;
+ *y++ = temp2;
+ --num;
+ }
}
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index 24dfc29..6a7b222 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -244,6 +244,10 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() {
if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
// Color conversion is needed.
free(mInputFrameData);
+ if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) {
+ ALOGE("Buffer size is too big.");
+ return OMX_ErrorUndefined;
+ }
mInputFrameData =
(uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
CHECK(mInputFrameData != NULL);
@@ -264,6 +268,10 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() {
int32_t nMacroBlocks = divUp(mWidth, 16) * divUp(mHeight, 16);
CHECK(mSliceGroup == NULL);
+ if ((size_t)nMacroBlocks > SIZE_MAX / sizeof(uint32_t)) {
+ ALOGE("requested memory size is too big.");
+ return OMX_ErrorUndefined;
+ }
mSliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
CHECK(mSliceGroup != NULL);
for (int ii = 0, idx = 0; ii < nMacroBlocks; ++ii) {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
index 90d7c6b..26de83d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -15,10 +15,21 @@
* and limitations under the License.
* -------------------------------------------------------------------
*/
+
+#include <stdint.h>
+
#include "mp4dec_lib.h"
#include "vlc_decode.h"
#include "bitstream.h"
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
#ifdef DEC_INTERNAL_MEMORY_OPT
@@ -95,6 +106,11 @@ OSCL_EXPORT_REF Bool PVInitVideoDecoder(VideoDecControls *decCtrl, uint8 *volbuf
#ifdef DEC_INTERNAL_MEMORY_OPT
video->vol = (Vol **) IMEM_VOL;
#else
+ if ((size_t)nLayers > SIZE_MAX / sizeof(Vol *)) {
+ status = PV_FALSE;
+ goto fail;
+ }
+
video->vol = (Vol **) oscl_malloc(nLayers * sizeof(Vol *));
#endif
if (video->vol == NULL) status = PV_FALSE;
@@ -128,6 +144,11 @@ OSCL_EXPORT_REF Bool PVInitVideoDecoder(VideoDecControls *decCtrl, uint8 *volbuf
else oscl_memset(video->prevVop, 0, sizeof(Vop));
video->memoryUsage += (sizeof(Vop) * 2);
+ if ((size_t)nLayers > SIZE_MAX / sizeof(Vop *)) {
+ status = PV_FALSE;
+ goto fail;
+ }
+
video->vopHeader = (Vop **) oscl_malloc(sizeof(Vop *) * nLayers);
#endif
if (video->vopHeader == NULL) status = PV_FALSE;
@@ -277,6 +298,7 @@ OSCL_EXPORT_REF Bool PVInitVideoDecoder(VideoDecControls *decCtrl, uint8 *volbuf
status = PV_FALSE;
}
+fail:
if (status == PV_FALSE) PVCleanUpVideoDecoder(decCtrl);
return status;
@@ -305,6 +327,10 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
video->nMBPerRow * video->nMBPerCol;
}
+ if (((uint64_t)video->width * video->height) > (uint64_t)INT32_MAX / sizeof(PIXEL)) {
+ return PV_FALSE;
+ }
+
size = (int32)sizeof(PIXEL) * video->width * video->height;
#ifdef PV_MEMORY_POOL
decCtrl->size = size;
@@ -320,6 +346,9 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
video->prevVop->uChan = video->prevVop->yChan + size;
video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
#else
+ if (size > INT32_MAX / 3) {
+ return PV_FALSE;
+ }
video->currVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
if (video->currVop->yChan == NULL) status = PV_FALSE;
@@ -347,6 +376,10 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
{
oscl_memset(video->prevEnhcVop, 0, sizeof(Vop));
#ifndef PV_MEMORY_POOL
+ if (size > INT32_MAX / 3) {
+ return PV_FALSE;
+ }
+
video->prevEnhcVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
if (video->prevEnhcVop->yChan == NULL) status = PV_FALSE;
video->prevEnhcVop->uChan = video->prevEnhcVop->yChan + size;
@@ -403,10 +436,17 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
if (video->acPredFlag == NULL) status = PV_FALSE;
video->memoryUsage += (nTotalMB);
+ if ((size_t)nTotalMB > SIZE_MAX / sizeof(typeDCStore)) {
+ return PV_FALSE;
+ }
video->predDC = (typeDCStore *) oscl_malloc(nTotalMB * sizeof(typeDCStore));
if (video->predDC == NULL) status = PV_FALSE;
video->memoryUsage += (nTotalMB * sizeof(typeDCStore));
+ if (nMBPerRow > INT32_MAX - 1
+ || (size_t)(nMBPerRow + 1) > SIZE_MAX / sizeof(typeDCACStore)) {
+ return PV_FALSE;
+ }
video->predDCAC_col = (typeDCACStore *) oscl_malloc((nMBPerRow + 1) * sizeof(typeDCACStore));
if (video->predDCAC_col == NULL) status = PV_FALSE;
video->memoryUsage += ((nMBPerRow + 1) * sizeof(typeDCACStore));
@@ -422,6 +462,10 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
video->headerInfo.CBP = (uint8 *) oscl_malloc(nTotalMB);
if (video->headerInfo.CBP == NULL) status = PV_FALSE;
video->memoryUsage += nTotalMB;
+
+ if ((size_t)nTotalMB > SIZE_MAX / sizeof(int16)) {
+ return PV_FALSE;
+ }
video->QPMB = (int16 *) oscl_malloc(nTotalMB * sizeof(int16));
if (video->QPMB == NULL) status = PV_FALSE;
video->memoryUsage += (nTotalMB * sizeof(int));
@@ -439,6 +483,9 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
video->memoryUsage += sizeof(MacroBlock);
}
/* Allocating motion vector space */
+ if ((size_t)nTotalMB > SIZE_MAX / (sizeof(MOT) * 4)) {
+ return PV_FALSE;
+ }
video->motX = (MOT *) oscl_malloc(sizeof(MOT) * 4 * nTotalMB);
if (video->motX == NULL) status = PV_FALSE;
video->motY = (MOT *) oscl_malloc(sizeof(MOT) * 4 * nTotalMB);
@@ -472,6 +519,9 @@ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLay
}
#else
+ if (nTotalMB > INT32_MAX / 6) {
+ return PV_FALSE;
+ }
video->pstprcTypCur = (uint8 *) oscl_malloc(nTotalMB * 6);
video->memoryUsage += (nTotalMB * 6);
if (video->pstprcTypCur == NULL)
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index 946e3d0..6c4510e 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -16,11 +16,20 @@
* -------------------------------------------------------------------
*/
+#include <stdint.h>
+
#include "mp4enc_lib.h"
#include "bitstream_io.h"
#include "rate_control.h"
#include "m4venc_oscl.h"
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
/* Inverse normal zigzag */
const static Int zigzag_i[NCOEFF_BLOCK] =
@@ -610,6 +619,10 @@ OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, Vid
max = temp_w * temp_h;
max_width = ((temp_w + 15) >> 4) << 4;
max_height = ((temp_h + 15) >> 4) << 4;
+ if (((uint64_t)max_width * max_height) > (uint64_t)INT32_MAX
+ || temp_w > INT32_MAX - 15 || temp_h > INT32_MAX - 15) {
+ goto CLEAN_UP;
+ }
nTotalMB = ((max_width * max_height) >> 8);
}
@@ -654,6 +667,9 @@ OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, Vid
/* Allocating motion vector space and interpolation memory*/
+ if ((size_t)nTotalMB > SIZE_MAX / sizeof(MOT *)) {
+ goto CLEAN_UP;
+ }
video->mot = (MOT **)M4VENC_MALLOC(sizeof(MOT *) * nTotalMB);
if (video->mot == NULL) goto CLEAN_UP;
@@ -676,11 +692,17 @@ OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, Vid
/* so that compilers can generate faster code to indexing the */
/* data inside (by using << instead of *). 04/14/2000. */
/* 5/29/01, use decoder lib ACDC prediction memory scheme. */
+ if ((size_t)nTotalMB > SIZE_MAX / sizeof(typeDCStore)) {
+ goto CLEAN_UP;
+ }
video->predDC = (typeDCStore *) M4VENC_MALLOC(nTotalMB * sizeof(typeDCStore));
if (video->predDC == NULL) goto CLEAN_UP;
if (!video->encParams->H263_Enabled)
{
+ if ((size_t)((max_width >> 4) + 1) > SIZE_MAX / sizeof(typeDCACStore)) {
+ goto CLEAN_UP;
+ }
video->predDCAC_col = (typeDCACStore *) M4VENC_MALLOC(((max_width >> 4) + 1) * sizeof(typeDCACStore));
if (video->predDCAC_col == NULL) goto CLEAN_UP;
@@ -688,6 +710,9 @@ OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, Vid
/* the rest will be used for storing horizontal (row) AC coefficients */
video->predDCAC_row = video->predDCAC_col + 1; /* ACDC */
+ if ((size_t)nTotalMB > SIZE_MAX / sizeof(Int)) {
+ goto CLEAN_UP;
+ }
video->acPredFlag = (Int *) M4VENC_MALLOC(nTotalMB * sizeof(Int)); /* Memory for acPredFlag */
if (video->acPredFlag == NULL) goto CLEAN_UP;
}
@@ -741,8 +766,15 @@ OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, Vid
offset = (pitch << 4) + 16;
max_height += 32;
}
+ if (((uint64_t)pitch * max_height) > (uint64_t)INT32_MAX) {
+ goto CLEAN_UP;
+ }
size = pitch * max_height;
+ if (size > INT32_MAX - (size >> 1)
+ || (size_t)(size + (size >> 1)) > SIZE_MAX / sizeof(PIXEL)) {
+ goto CLEAN_UP;
+ }
video->currVop->yChan = (PIXEL *)M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for currVop Y */
if (video->currVop->yChan == NULL) goto CLEAN_UP;
video->currVop->uChan = video->currVop->yChan + size;/* Memory for currVop U */
@@ -841,6 +873,9 @@ OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, Vid
/* /// End /////////////////////////////////////// */
+ if ((size_t)nLayers > SIZE_MAX / sizeof(Vol *)) {
+ goto CLEAN_UP;
+ }
video->vol = (Vol **)M4VENC_MALLOC(nLayers * sizeof(Vol *)); /* Memory for VOL pointers */
/* Memory allocation and Initialization of Vols and writing of headers */
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 8a95643..f026761 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -147,7 +147,7 @@ void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
}
outHeader->nOffset = 0;
- outHeader->nFilledLen = (width * height * 3) / 2;
+ outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0;
outHeader->nTimeStamp = inHeader->nTimeStamp;
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index b8084ae..ed52a37 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -34,6 +34,12 @@ namespace android {
static const int kRate = 48000;
+// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
+// mappings for up to 8 channels. This information is part of the Vorbis I
+// Specification:
+// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
+static const int kMaxChannels = 8;
+
template<class T>
static void InitOMXParams(T *params) {
params->nSize = sizeof(T);
@@ -101,7 +107,7 @@ void SoftOpus::initPorts() {
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
+ def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t) * kMaxChannels;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
@@ -225,12 +231,6 @@ static uint16_t ReadLE16(const uint8_t *data, size_t data_size,
return val;
}
-// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
-// mappings for up to 8 channels. This information is part of the Vorbis I
-// Specification:
-// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
-static const int kMaxChannels = 8;
-
// Maximum packet size used in Xiph's opusdec.
static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 106b338..632367e 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -181,7 +181,7 @@ void SoftwareRenderer::resetFormatIfChanged(const sp<AMessage> &format) {
}
void SoftwareRenderer::render(
- const void *data, size_t /*size*/, int64_t timestampNs,
+ const void *data, size_t size, int64_t timestampNs,
void* /*platformPrivate*/, const sp<AMessage>& format) {
resetFormatIfChanged(format);
@@ -210,6 +210,9 @@ void SoftwareRenderer::render(
buf->stride, buf->height,
0, 0, mCropWidth - 1, mCropHeight - 1);
} else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
+ if ((size_t)mWidth * mHeight * 3 / 2 > size) {
+ goto skip_copying;
+ }
const uint8_t *src_y = (const uint8_t *)data;
const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
@@ -239,6 +242,10 @@ void SoftwareRenderer::render(
}
} else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
+ if ((size_t)mWidth * mHeight * 3 / 2 > size) {
+ goto skip_copying;
+ }
+
const uint8_t *src_y =
(const uint8_t *)data;
@@ -275,6 +282,7 @@ void SoftwareRenderer::render(
LOG_ALWAYS_FATAL("bad color format %#x", mColorFormat);
}
+skip_copying:
CHECK_EQ(0, mapper.unlock(buf->handle));
if ((err = native_window_set_buffers_timestamp(mNativeWindow.get(),
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
index b214870..4913fd4 100644
--- a/media/libstagefright/foundation/ABuffer.cpp
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -25,12 +25,17 @@ namespace android {
ABuffer::ABuffer(size_t capacity)
: mMediaBufferBase(NULL),
- mData(malloc(capacity)),
- mCapacity(capacity),
mRangeOffset(0),
- mRangeLength(capacity),
mInt32Data(0),
mOwnsData(true) {
+ mData = malloc(capacity);
+ if (mData == NULL) {
+ mCapacity = 0;
+ mRangeLength = 0;
+ } else {
+ mCapacity = capacity;
+ mRangeLength = capacity;
+ }
}
ABuffer::ABuffer(void *data, size_t capacity)
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 93447c6..5496dbf 100755
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -328,7 +328,7 @@ bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
size_t oldSize = mSize;
size_t offset = 0;
- while (offset + 10 <= mSize) {
+ while (mSize >= 10 && offset <= mSize - 10) {
if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
break;
}
@@ -340,7 +340,7 @@ bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
return false;
}
- if (offset + dataSize + 10 > mSize) {
+ if (dataSize > mSize - 10 - offset) {
return false;
}
@@ -350,6 +350,9 @@ bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
if (flags & 1) {
// Strip data length indicator
+ if (mSize < 14 || mSize - 14 < offset || dataSize < 4) {
+ return false;
+ }
memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
mSize -= 4;
dataSize -= 4;
@@ -550,6 +553,9 @@ void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
return;
}
+ if (mFrameSize < getHeaderLength() + 1) {
+ return;
+ }
size_t n = mFrameSize - getHeaderLength() - 1;
if (otherdata) {
// skip past the encoding, language, and the 0 separator
@@ -735,6 +741,11 @@ void ID3::Iterator::findFrame() {
mFrameSize += 6;
+ // Prevent integer overflow in validation
+ if (SIZE_MAX - mOffset <= mFrameSize) {
+ return;
+ }
+
if (mOffset + mFrameSize > mParent.mSize) {
ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6);
@@ -764,7 +775,7 @@ void ID3::Iterator::findFrame() {
return;
}
- size_t baseSize;
+ size_t baseSize = 0;
if (mParent.mVersion == ID3_V2_4) {
if (!ParseSyncsafeInteger(
&mParent.mData[mOffset + 4], &baseSize)) {
@@ -774,7 +785,21 @@ void ID3::Iterator::findFrame() {
baseSize = U32_AT(&mParent.mData[mOffset + 4]);
}
- mFrameSize = 10 + baseSize;
+ if (baseSize == 0) {
+ return;
+ }
+
+ // Prevent integer overflow when adding
+ if (SIZE_MAX - 10 <= baseSize) {
+ return;
+ }
+
+ mFrameSize = 10 + baseSize; // add tag id, size field and flags
+
+ // Prevent integer overflow in validation
+ if (SIZE_MAX - mOffset <= mFrameSize) {
+ return;
+ }
if (mOffset + mFrameSize > mParent.mSize) {
ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
@@ -907,6 +932,13 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const {
size_t descLen = StringSize(&data[2 + mimeLen], encoding);
+ if (size < 2 ||
+ size - 2 < mimeLen ||
+ size - 2 - mimeLen < descLen) {
+ ALOGW("bogus album art sizes");
+ return NULL;
+ }
+
*length = size - 2 - mimeLen - descLen;
return &data[2 + mimeLen + descLen];
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 3ba2431..5726f6c 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -167,8 +167,9 @@ private:
// normally we don't round
inline uint64_t getSampleTime(
size_t sample_index, uint64_t scale_num, uint64_t scale_den) const {
- return (mSampleTimeEntries[sample_index].mCompositionTime
- * scale_num) / scale_den;
+ return (sample_index < (size_t)mNumSampleSizes && mSampleTimeEntries != NULL
+ && scale_den != 0)
+ ? (mSampleTimeEntries[sample_index].mCompositionTime * scale_num) / scale_den : 0;
}
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 4f0862c..105376a 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -21,6 +21,7 @@
#include "MatroskaExtractor.h"
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
@@ -631,7 +632,12 @@ status_t MatroskaSource::read(
TRESPASS();
}
- if (srcOffset + mNALSizeLen + NALsize > srcSize) {
+ if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
+ frame->release();
+ frame = NULL;
+
+ return ERROR_MALFORMED;
+ } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
break;
}
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index aa8ffc6..851805f 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -404,8 +404,9 @@ sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) {
break;
}
}
-
- CHECK_LE(offset + payloadLength, buffer->size());
+
+ CHECK_LT(offset, buffer->size());
+ CHECK_LE(payloadLength, buffer->size() - offset);
memcpy(out->data() + out->size(), &ptr[offset], payloadLength);
out->setRange(0, out->size() + payloadLength);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 283fb02..4ed19e9 100755
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -751,8 +751,12 @@ status_t AudioFlinger::setMasterVolume(float value)
// assigned to HALs which do not have master volume support will apply
// master volume during the mix operation. Threads with HALs which do
// support master volume will simply ignore the setting.
- for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
+ continue;
+ }
mPlaybackThreads.valueAt(i)->setMasterVolume(value);
+ }
return NO_ERROR;
}
@@ -863,8 +867,12 @@ status_t AudioFlinger::setMasterMute(bool muted)
// assigned to HALs which do not have master mute support will apply master
// mute during the mix operation. Threads with HALs which do support master
// mute will simply ignore the setting.
- for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
+ continue;
+ }
mPlaybackThreads.valueAt(i)->setMasterMute(muted);
+ }
return NO_ERROR;
}
@@ -1859,11 +1867,10 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
if (thread->type() == ThreadBase::MIXER) {
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
+ if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
DuplicatingThread *dupThread =
(DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
dupThread->removeOutputTrack((MixerThread *)thread.get());
-
}
}
}
@@ -1890,7 +1897,7 @@ status_t AudioFlinger::closeOutput_nonvirtual(audio_io_handle_t output)
// The thread entity (active unit of execution) is no longer running here,
// but the ThreadBase container still exists.
- if (thread->type() != ThreadBase::DUPLICATING) {
+ if (!thread->isDuplicating()) {
closeOutputFinish(thread);
}
@@ -2336,6 +2343,9 @@ AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
{
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ if(thread->isDuplicating()) {
+ continue;
+ }
AudioStreamOut *output = thread->getOutput();
if (output != NULL && output->audioHwDev == mPrimaryHardwareDev) {
return thread;
@@ -2649,7 +2659,7 @@ status_t AudioFlinger::moveEffectChain_l(int sessionId,
// Check whether the destination thread has a channel count of FCC_2, which is
// currently required for (most) effects. Prevent moving the effect chain here rather
// than disabling the addEffect_l() call in dstThread below.
- if ((dstThread->type() == ThreadBase::MIXER || dstThread->type() == ThreadBase::DUPLICATING) &&
+ if ((dstThread->type() == ThreadBase::MIXER || dstThread->isDuplicating()) &&
dstThread->mChannelCount != FCC_2) {
ALOGW("moveEffectChain_l() effect chain failed because"
" destination thread %p channel count(%u) != %u",
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9fccda1..5282ffe 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4864,10 +4864,13 @@ void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
mOutputTracks[i]->destroy();
mOutputTracks.removeAt(i);
updateWaitTime_l();
+ if (thread->getOutput() == mOutput) {
+ mOutput = NULL;
+ }
return;
}
}
- ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
+ ALOGV("removeOutputTrack(): unknown thread: %p", thread);
}
// caller must hold mLock
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1088843..56a42a8 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -229,6 +229,8 @@ public:
// static externally-visible
type_t type() const { return mType; }
+ bool isDuplicating() const { return (mType == DUPLICATING); }
+
audio_io_handle_t id() const { return mId;}
// dynamic externally-visible