Code: bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset) {
 List<BufferInfo *> &outQueue = getPortQueue(1);
 BufferInfo *outInfo = NULL;
    OMX_BUFFERHEADERTYPE *outHeader = NULL;
 vpx_codec_iter_t iter = NULL;

 if (flushDecoder && mFrameParallelMode) {
 if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx, NULL, 0, NULL, 0)) {
            ALOGE("Failed to flush on2 decoder.");
 return false;
 }
 }

 if (!display) {
 if (!flushDecoder) {
            ALOGE("Invalid operation.");
 return false;
 }
 while ((mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter))) {
 }
 return true;
 }

 while (!outQueue.empty()) {
 if (mImg == NULL) {
            mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
 if (mImg == NULL) {
 break;
 }
 }
 uint32_t width = mImg->d_w;
 uint32_t height = mImg->d_h;
        outInfo = *outQueue.begin();
        outHeader = outInfo->mHeader;
        CHECK_EQ(mImg->fmt, VPX_IMG_FMT_I420);
        handlePortSettingsChange(portWillReset, width, height);
 if (*portWillReset) {
 return true;
 }

        outHeader->nOffset = 0;

         outHeader->nFlags = 0;
         outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
         outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv;
        if (outHeader->nAllocLen >= outHeader->nFilledLen) {
             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];
 const uint8_t *srcV = (const uint8_t *)mImg->planes[VPX_PLANE_V];
 size_t srcYStride = mImg->stride[VPX_PLANE_Y];
 size_t srcUStride = mImg->stride[VPX_PLANE_U];

             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;
         }
 
        mImg = NULL;
        outInfo->mOwnedByUs = false;
        outQueue.erase(outQueue.begin());
        outInfo = NULL;
        notifyFillBufferDone(outHeader);
        outHeader = NULL;
 }

 if (!eos) {
 return true;
 }

 if (!outQueue.empty()) {
        outInfo = *outQueue.begin();
        outQueue.erase(outQueue.begin());
        outHeader = outInfo->mHeader;
        outHeader->nTimeStamp = 0;
        outHeader->nFilledLen = 0;
        outHeader->nFlags = OMX_BUFFERFLAG_EOS;
        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);
        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
 }

     return true;
 }

Vulnerability Type: Overflow +Priv 
CWE ID: CWE-119
Summary: Buffer overflow in codecs/on2/dec/SoftVPX.cpp in libstagefright in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-09-01, and 7.0 before 2016-09-01 allows attackers to gain privileges via a crafted application, aka internal bug 29421675.
Commit Message: SoftVPX: fix nFilledLen overflow

Bug: 29421675
Change-Id: I25d4cf54a5df22c2130c37e95c7c7f75063111f3
