Merge "Clear unused pointer field when sending across binder" into klp-dev
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 157b1aa..6c64a2c 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -19,7 +19,7 @@
 #define DATA_SOURCE_H_
 
 #include <sys/types.h>
-
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
@@ -58,6 +58,20 @@
     bool getUInt32(off64_t offset, uint32_t *x);
     bool getUInt64(off64_t offset, uint64_t *x);
 
+    // Reads in "count" entries of type T into vector *x.
+    // Returns true if "count" entries can be read.
+    // If fewer than "count" entries can be read, return false. In this case,
+    // the output vector *x will still have those entries that were read. Call
+    // x->size() to obtain the number of entries read.
+    // The optional parameter chunkSize specifies how many entries should be
+    // read from the data source at one time into a temporary buffer. Increasing
+    // chunkSize can improve the performance at the cost of extra memory usage.
+    // The default value for chunkSize is set to read at least 4k bytes at a
+    // time, depending on sizeof(T).
+    template <typename T>
+    bool getVector(off64_t offset, Vector<T>* x, size_t count,
+                   size_t chunkSize = (4095 / sizeof(T)) + 1);
+
     // May return ERROR_UNSUPPORTED.
     virtual status_t getSize(off64_t *size);
 
@@ -108,6 +122,51 @@
     DataSource &operator=(const DataSource &);
 };
 
+template <typename T>
+bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count,
+                           size_t chunkSize)
+{
+    x->clear();
+    if (chunkSize == 0) {
+        return false;
+    }
+    if (count == 0) {
+        return true;
+    }
+
+    T tmp[chunkSize];
+    ssize_t numBytesRead;
+    size_t numBytesPerChunk = chunkSize * sizeof(T);
+    size_t i;
+
+    for (i = 0; i + chunkSize < count; i += chunkSize) {
+        // This loops is executed when more than chunkSize records need to be
+        // read.
+        numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk);
+        if (numBytesRead == -1) { // If readAt() returns -1, there is an error.
+            return false;
+        }
+        if (numBytesRead < numBytesPerChunk) {
+            // This case is triggered when the stream ends before the whole
+            // chunk is read.
+            x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+            return false;
+        }
+        x->appendArray(tmp, chunkSize);
+        offset += numBytesPerChunk;
+    }
+
+    // There are (count - i) more records to read.
+    // Right now, (count - i) <= chunkSize.
+    // We do the same thing as above, but with chunkSize replaced by count - i.
+    numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T));
+    if (numBytesRead == -1) {
+        return false;
+    }
+    x->appendArray(tmp, (size_t)numBytesRead / sizeof(T));
+    return x->size() == count;
+}
+
 }  // namespace android
 
 #endif  // DATA_SOURCE_H_
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4b3ad68..3e585c6 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -654,9 +654,11 @@
     OMX_U32 index = 0;
     for (;;) {
         format.nIndex = index;
+        ALOGI("calling getparam %d size %d", index, format.nSize);
         status_t err = mOMX->getParameter(
                 mNode, OMX_IndexParamVideoPortFormat,
                 &format, sizeof(format));
+        ALOGI("called getparam %d size %d: %d", index, format.nSize, err);
 
         if (err != OK) {
             return err;
@@ -690,9 +692,11 @@
     }
 
     CODEC_LOGV("found a match.");
+    ALOGI("calling setparam size %d", format.nSize);
     status_t err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoPortFormat,
             &format, sizeof(format));
+    ALOGI("called setparam: %d", err);
 
     return err;
 }
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index dfc3713..b71c4a7 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -121,8 +121,9 @@
       mSampleSizeFieldSize(0),
       mDefaultSampleSize(0),
       mNumSampleSizes(0),
+      mHasTimeToSample(false),
       mTimeToSampleCount(0),
-      mTimeToSample(NULL),
+      mTimeToSample(),
       mSampleTimeEntries(NULL),
       mCompositionTimeDeltaEntries(NULL),
       mNumCompositionTimeDeltaEntries(0),
@@ -151,9 +152,6 @@
     delete[] mSampleTimeEntries;
     mSampleTimeEntries = NULL;
 
-    delete[] mTimeToSample;
-    mTimeToSample = NULL;
-
     delete mSampleIterator;
     mSampleIterator = NULL;
 }
@@ -162,7 +160,7 @@
     return mChunkOffsetOffset >= 0
         && mSampleToChunkOffset >= 0
         && mSampleSizeOffset >= 0
-        && mTimeToSample != NULL;
+        && mHasTimeToSample;
 }
 
 status_t SampleTable::setChunkOffsetParams(
@@ -326,7 +324,7 @@
 
 status_t SampleTable::setTimeToSampleParams(
         off64_t data_offset, size_t data_size) {
-    if (mTimeToSample != NULL || data_size < 8) {
+    if (mHasTimeToSample || data_size < 8) {
         return ERROR_MALFORMED;
     }
 
@@ -342,22 +340,31 @@
     }
 
     mTimeToSampleCount = U32_AT(&header[4]);
-    uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
-    if (allocSize > SIZE_MAX) {
+    if ((uint64_t)mTimeToSampleCount >
+        (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) {
+        // Choose this bound because
+        // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
+        //    time-to-sample entry in the time-to-sample table.
+        // 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.");
         return ERROR_OUT_OF_RANGE;
     }
-    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
 
-    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
-    if (mDataSource->readAt(
-                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
+    // 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.");
         return ERROR_IO;
     }
 
-    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
-        mTimeToSample[i] = ntohl(mTimeToSample[i]);
+    for (size_t i = 0; i < mTimeToSample.size(); ++i) {
+        mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]);
     }
 
+    mHasTimeToSample = true;
     return OK;
 }
 
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index 9423481..2fa558a 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -468,6 +468,10 @@
             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (formatParams->nPortIndex > 1) {
                 return OMX_ErrorUndefined;
             }
@@ -535,6 +539,10 @@
             OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
                 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
 
+            if (!isValidOMXParam(profileLevel)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (profileLevel->nPortIndex != 1) {
                 return OMX_ErrorUndefined;
             }
@@ -589,6 +597,11 @@
         {
             OMX_PARAM_PORTDEFINITIONTYPE *def =
                 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+            if (!isValidOMXParam(def)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (def->nPortIndex > 1) {
                 return OMX_ErrorUndefined;
             }
@@ -629,6 +642,10 @@
             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
 
+            if (!isValidOMXParam(roleParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (strncmp((const char *)roleParams->cRole,
                         "video_encoder.avc",
                         OMX_MAX_STRINGNAME_SIZE - 1)) {
@@ -643,6 +660,10 @@
             const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                 (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (formatParams->nPortIndex > 1) {
                 return OMX_ErrorUndefined;
             }
@@ -713,6 +734,11 @@
         {
             StoreMetaDataInBuffersParams *storeParams =
                     (StoreMetaDataInBuffersParams*)params;
+
+            if (!isValidOMXParam(storeParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (storeParams->nPortIndex != 0) {
                 ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
                         __FUNCTION__);
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index ba92107..ea7dacf 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -230,6 +230,15 @@
             mSignalledError = true;
         }
 
+        if (inHeader->nFilledLen * sizeof(int16_t) > outHeader->nAllocLen) {
+            ALOGE("output buffer too small (%d).", outHeader->nAllocLen);
+            android_errorWriteLog(0x534e4554, "27793163");
+
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            mSignalledError = true;
+            return;
+        }
+
         const uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
 
         if (mIsMLaw) {
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index d123f9f..5132b63 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -225,6 +225,14 @@
             mSignalledError = true;
         }
 
+        if (outHeader->nAllocLen < (inHeader->nFilledLen / 65) * 320) {
+            ALOGE("output buffer is not large enough (%d).", outHeader->nAllocLen);
+            android_errorWriteLog(0x534e4554, "27793367");
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            mSignalledError = true;
+            return;
+        }
+
         uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
 
         int n = mSignalledError ? 0 : DecodeGSM(mGsm,
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 199ff02..9d41351 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -335,6 +335,10 @@
             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (formatParams->nPortIndex > 1) {
                 return OMX_ErrorUndefined;
             }
@@ -422,6 +426,10 @@
             OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
                 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
 
+            if (!isValidOMXParam(profileLevel)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (profileLevel->nPortIndex != 1) {
                 return OMX_ErrorUndefined;
             }
@@ -478,6 +486,11 @@
         {
             OMX_PARAM_PORTDEFINITIONTYPE *def =
                 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+            if (!isValidOMXParam(def)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (def->nPortIndex > 1) {
                 return OMX_ErrorUndefined;
             }
@@ -521,6 +534,10 @@
             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
 
+            if (!isValidOMXParam(roleParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (strncmp((const char *)roleParams->cRole,
                         (mEncodeMode == H263_MODE)
                             ? "video_encoder.h263": "video_encoder.mpeg4",
@@ -536,6 +553,10 @@
             const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                 (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (formatParams->nPortIndex > 1) {
                 return OMX_ErrorUndefined;
             }
@@ -627,6 +648,11 @@
         {
             StoreMetaDataInBuffersParams *storeParams =
                     (StoreMetaDataInBuffersParams*)params;
+
+            if (!isValidOMXParam(storeParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (storeParams->nPortIndex != 0) {
                 ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
                         __FUNCTION__);
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index de993c5..80c29ab 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -353,6 +353,10 @@
             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
 
+            if (!isValidOMXParam(formatParams)) {
+                return OMX_ErrorBadParameter;
+            }
+
             if (formatParams->nPortIndex == kInputPortIndex) {
                 if (formatParams->nIndex >= kNumberOfSupportedColorFormats) {
                     return OMX_ErrorNoMore;
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 847dff7..caa028a 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -24,6 +24,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
+#include <utils/Vector.h>
 
 namespace android {
 
@@ -108,8 +109,9 @@
     uint32_t mDefaultSampleSize;
     uint32_t mNumSampleSizes;
 
+    bool mHasTimeToSample;
     uint32_t mTimeToSampleCount;
-    uint32_t *mTimeToSample;
+    Vector<uint32_t> mTimeToSample;
 
     struct SampleTimeEntry {
         uint32_t mSampleIndex;