void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) {
 if (mSignalledError) {
 return;
 }

 List<BufferInfo *> &inQueue = getPortQueue(0);
 List<BufferInfo *> &outQueue = getPortQueue(1);

 if (!mSentCodecSpecificData) {

 if (outQueue.empty()) {
 return;
 }

 if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
            ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
            mSignalledError = true;
 return;
 }

        OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
 if (mBitRate != actualBitRate) {
            ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
 }

        AACENC_InfoStruct encInfo;
 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
            ALOGE("Failed to get AAC encoder info");
            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
            mSignalledError = true;
 return;
 }

         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
         outHeader->nFilledLen = encInfo.confSize;
         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;

 uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
        memcpy(out, encInfo.confBuf, encInfo.confSize);

        outQueue.erase(outQueue.begin());
        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        mSentCodecSpecificData = true;
 }

 size_t numBytesPerInputFrame =
        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);

 if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
        numBytesPerInputFrame = 512;
 }

 for (;;) {

 while (mInputSize < numBytesPerInputFrame) {

 if (mSawInputEOS || inQueue.empty()) {
 return;
 }

 BufferInfo *inInfo = *inQueue.begin();
            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

 const void *inData = inHeader->pBuffer + inHeader->nOffset;

 size_t copy = numBytesPerInputFrame - mInputSize;
 if (copy > inHeader->nFilledLen) {
                copy = inHeader->nFilledLen;
 }

 if (mInputFrame == NULL) {
                mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
 }

 if (mInputSize == 0) {
                mInputTimeUs = inHeader->nTimeStamp;
 }

            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
            mInputSize += copy;

            inHeader->nOffset += copy;
            inHeader->nFilledLen -= copy;

            inHeader->nTimeStamp +=
 (copy * 1000000ll / mSampleRate)
 / (mNumChannels * sizeof(int16_t));

 if (inHeader->nFilledLen == 0) {
 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                    mSawInputEOS = true;

                    memset((uint8_t *)mInputFrame + mInputSize,
 0,
                           numBytesPerInputFrame - mInputSize);

                    mInputSize = numBytesPerInputFrame;
 }

                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);

                inData = NULL;
                inHeader = NULL;
                inInfo = NULL;
 }
 }

 if (outQueue.empty()) {
 return;
 }

 BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

 uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
 size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;

        AACENC_InArgs inargs;
        AACENC_OutArgs outargs;
        memset(&inargs, 0, sizeof(inargs));
        memset(&outargs, 0, sizeof(outargs));
        inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);

 void* inBuffer[] = { (unsigned char *)mInputFrame };
        INT   inBufferIds[] = { IN_AUDIO_DATA };
        INT   inBufferSize[] = { (INT)numBytesPerInputFrame };
        INT   inBufferElSize[] = { sizeof(int16_t) };

        AACENC_BufDesc inBufDesc;
        inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
        inBufDesc.bufs              = (void**)&inBuffer;
        inBufDesc.bufferIdentifiers = inBufferIds;
        inBufDesc.bufSizes          = inBufferSize;
        inBufDesc.bufElSizes        = inBufferElSize;

 void* outBuffer[] = { outPtr };
        INT   outBufferIds[] = { OUT_BITSTREAM_DATA };
        INT   outBufferSize[] = { 0 };
        INT   outBufferElSize[] = { sizeof(UCHAR) };

        AACENC_BufDesc outBufDesc;
        outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
        outBufDesc.bufs              = (void**)&outBuffer;
        outBufDesc.bufferIdentifiers = outBufferIds;
        outBufDesc.bufSizes          = outBufferSize;
        outBufDesc.bufElSizes        = outBufferElSize;

        AACENC_ERROR encoderErr = AACENC_OK;
 size_t nOutputBytes = 0;

 do {
            memset(&outargs, 0, sizeof(outargs));

            outBuffer[0] = outPtr;
            outBufferSize[0] = outAvailable - nOutputBytes;

            encoderErr = aacEncEncode(mAACEncoder,
 &inBufDesc,
 &outBufDesc,
 &inargs,
 &outargs);

 if (encoderErr == AACENC_OK) {
                outPtr += outargs.numOutBytes;
                nOutputBytes += outargs.numOutBytes;

 if (outargs.numInSamples > 0) {
 int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
 if (numRemainingSamples > 0) {
                        memmove(mInputFrame,
 &mInputFrame[outargs.numInSamples],
 sizeof(int16_t) * numRemainingSamples);
 }
                    inargs.numInSamples -= outargs.numInSamples;
 }
 }
 } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);

        outHeader->nFilledLen = nOutputBytes;

        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;

 if (mSawInputEOS) {
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
 }

        outHeader->nTimeStamp = mInputTimeUs;

#if 0
        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
              nOutputBytes, mInputTimeUs, outHeader->nFlags);

        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
#endif

        outQueue.erase(outQueue.begin());
        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        outHeader = NULL;
        outInfo = NULL;

        mInputSize = 0;
 }
}

An elevation of privilege vulnerability in codecs/aacenc/SoftAACEncoder2.cpp in libstagefright in Mediaserver could enable a local malicious application to execute arbitrary code within the context of a privileged process. This issue is rated as High because it could be used to gain local access to elevated capabilities, which are not normally accessible to a third-party application. Product: Android. Versions: 4.4.4, 5.0.2, 5.1.1, 6.0, 6.0.1, 7.0, 7.1.1, 7.1.2. Android ID: A-34617444.


void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) {
 if (mSignalledError) {
 return;
 }

 List<BufferInfo *> &inQueue = getPortQueue(0);
 List<BufferInfo *> &outQueue = getPortQueue(1);

 if (!mSentCodecSpecificData) {

 if (outQueue.empty()) {
 return;
 }

 if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
            ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
            mSignalledError = true;
 return;
 }

        OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
 if (mBitRate != actualBitRate) {
            ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
 }

        AACENC_InfoStruct encInfo;
 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
            ALOGE("Failed to get AAC encoder info");
            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
            mSignalledError = true;
 return;
 }

         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

        if (outHeader->nOffset + encInfo.confSize > outHeader->nAllocLen) {
            ALOGE("b/34617444");
            android_errorWriteLog(0x534e4554,"34617444");
            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
            mSignalledError = true;
            return;
        }

         outHeader->nFilledLen = encInfo.confSize;
         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;

 uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
        memcpy(out, encInfo.confBuf, encInfo.confSize);

        outQueue.erase(outQueue.begin());
        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        mSentCodecSpecificData = true;
 }

 size_t numBytesPerInputFrame =
        mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);

 if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
        numBytesPerInputFrame = 512;
 }

 for (;;) {

 while (mInputSize < numBytesPerInputFrame) {

 if (mSawInputEOS || inQueue.empty()) {
 return;
 }

 BufferInfo *inInfo = *inQueue.begin();
            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

 const void *inData = inHeader->pBuffer + inHeader->nOffset;

 size_t copy = numBytesPerInputFrame - mInputSize;
 if (copy > inHeader->nFilledLen) {
                copy = inHeader->nFilledLen;
 }

 if (mInputFrame == NULL) {
                mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
 }

 if (mInputSize == 0) {
                mInputTimeUs = inHeader->nTimeStamp;
 }

            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
            mInputSize += copy;

            inHeader->nOffset += copy;
            inHeader->nFilledLen -= copy;

            inHeader->nTimeStamp +=
 (copy * 1000000ll / mSampleRate)
 / (mNumChannels * sizeof(int16_t));

 if (inHeader->nFilledLen == 0) {
 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                    mSawInputEOS = true;

                    memset((uint8_t *)mInputFrame + mInputSize,
 0,
                           numBytesPerInputFrame - mInputSize);

                    mInputSize = numBytesPerInputFrame;
 }

                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);

                inData = NULL;
                inHeader = NULL;
                inInfo = NULL;
 }
 }

 if (outQueue.empty()) {
 return;
 }

 BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

 uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
 size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;

        AACENC_InArgs inargs;
        AACENC_OutArgs outargs;
        memset(&inargs, 0, sizeof(inargs));
        memset(&outargs, 0, sizeof(outargs));
        inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);

 void* inBuffer[] = { (unsigned char *)mInputFrame };
        INT   inBufferIds[] = { IN_AUDIO_DATA };
        INT   inBufferSize[] = { (INT)numBytesPerInputFrame };
        INT   inBufferElSize[] = { sizeof(int16_t) };

        AACENC_BufDesc inBufDesc;
        inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
        inBufDesc.bufs              = (void**)&inBuffer;
        inBufDesc.bufferIdentifiers = inBufferIds;
        inBufDesc.bufSizes          = inBufferSize;
        inBufDesc.bufElSizes        = inBufferElSize;

 void* outBuffer[] = { outPtr };
        INT   outBufferIds[] = { OUT_BITSTREAM_DATA };
        INT   outBufferSize[] = { 0 };
        INT   outBufferElSize[] = { sizeof(UCHAR) };

        AACENC_BufDesc outBufDesc;
        outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
        outBufDesc.bufs              = (void**)&outBuffer;
        outBufDesc.bufferIdentifiers = outBufferIds;
        outBufDesc.bufSizes          = outBufferSize;
        outBufDesc.bufElSizes        = outBufferElSize;

        AACENC_ERROR encoderErr = AACENC_OK;
 size_t nOutputBytes = 0;

 do {
            memset(&outargs, 0, sizeof(outargs));

            outBuffer[0] = outPtr;
            outBufferSize[0] = outAvailable - nOutputBytes;

            encoderErr = aacEncEncode(mAACEncoder,
 &inBufDesc,
 &outBufDesc,
 &inargs,
 &outargs);

 if (encoderErr == AACENC_OK) {
                outPtr += outargs.numOutBytes;
                nOutputBytes += outargs.numOutBytes;

 if (outargs.numInSamples > 0) {
 int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
 if (numRemainingSamples > 0) {
                        memmove(mInputFrame,
 &mInputFrame[outargs.numInSamples],
 sizeof(int16_t) * numRemainingSamples);
 }
                    inargs.numInSamples -= outargs.numInSamples;
 }
 }
 } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);

        outHeader->nFilledLen = nOutputBytes;

        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;

 if (mSawInputEOS) {
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
 }

        outHeader->nTimeStamp = mInputTimeUs;

#if 0
        ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
              nOutputBytes, mInputTimeUs, outHeader->nFlags);

        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
#endif

        outQueue.erase(outQueue.begin());
        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        outHeader = NULL;
        outInfo = NULL;

        mInputSize = 0;
 }
}


WORD32 ih264d_decode_gaps_in_frame_num(dec_struct_t *ps_dec,
                                       UWORD16 u2_frame_num)
{
    UWORD32 u4_next_frm_num, u4_start_frm_num;
    UWORD32 u4_max_frm_num;
 pocstruct_t s_tmp_poc;
    WORD32 i4_poc;
 dec_slice_params_t *ps_cur_slice;

 dec_pic_params_t *ps_pic_params;
    WORD8 i1_gap_idx;
    WORD32 *i4_gaps_start_frm_num;
 dpb_manager_t *ps_dpb_mgr;
    WORD32 i4_frame_gaps;
    WORD8 *pi1_gaps_per_seq;
    WORD32 ret;

    ps_cur_slice = ps_dec->ps_cur_slice;
 if(ps_cur_slice->u1_field_pic_flag)
 {
 if(ps_dec->u2_prev_ref_frame_num == u2_frame_num)
 return 0;
 }

    u4_next_frm_num = ps_dec->u2_prev_ref_frame_num + 1;
    u4_max_frm_num = ps_dec->ps_cur_sps->u2_u4_max_pic_num_minus1 + 1;

 if(u4_next_frm_num >= u4_max_frm_num)
 {
        u4_next_frm_num -= u4_max_frm_num;
 }

 if(u4_next_frm_num == u2_frame_num)
 {
 return (0);
 }

 if((ps_dec->u1_nal_unit_type == IDR_SLICE_NAL)
 && (u4_next_frm_num >= u2_frame_num))
 {
 return (0);
 }
    u4_start_frm_num = u4_next_frm_num;

    s_tmp_poc.i4_pic_order_cnt_lsb = 0;
    s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0;
    s_tmp_poc.i4_pic_order_cnt_lsb = 0;
    s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0;
    s_tmp_poc.i4_delta_pic_order_cnt[0] = 0;
    s_tmp_poc.i4_delta_pic_order_cnt[1] = 0;

     ps_cur_slice = ps_dec->ps_cur_slice;
     ps_pic_params = ps_dec->ps_cur_pps;
    ps_cur_slice->u1_field_pic_flag = 0;

     i4_frame_gaps = 0;
     ps_dpb_mgr = ps_dec->ps_dpb_mgr;

 /* Find a empty slot to store gap seqn info */
    i4_gaps_start_frm_num = ps_dpb_mgr->ai4_gaps_start_frm_num;
 for(i1_gap_idx = 0; i1_gap_idx < MAX_FRAMES; i1_gap_idx++)
 {
 if(INVALID_FRAME_NUM == i4_gaps_start_frm_num[i1_gap_idx])
 break;
 }
 if(MAX_FRAMES == i1_gap_idx)
 {
        UWORD32 i4_error_code;
        i4_error_code = ERROR_DBP_MANAGER_T;
 return i4_error_code;
 }

    i4_poc = 0;
    i4_gaps_start_frm_num[i1_gap_idx] = u4_start_frm_num;
    ps_dpb_mgr->ai4_gaps_end_frm_num[i1_gap_idx] = u2_frame_num - 1;
    pi1_gaps_per_seq = ps_dpb_mgr->ai1_gaps_per_seq;
    pi1_gaps_per_seq[i1_gap_idx] = 0;
 while(u4_next_frm_num != u2_frame_num)
 {
        ih264d_delete_nonref_nondisplay_pics(ps_dpb_mgr);
 if(ps_pic_params->ps_sps->u1_pic_order_cnt_type)
 {
 /* allocate a picture buffer and insert it as ST node */
            ret = ih264d_decode_pic_order_cnt(0, u4_next_frm_num,
 &ps_dec->s_prev_pic_poc,
 &s_tmp_poc, ps_cur_slice,
                                              ps_pic_params, 1, 0, 0,
 &i4_poc);
 if(ret != OK)
 return ret;

 /* Display seq no calculations */
 if(i4_poc >= ps_dec->i4_max_poc)
                ps_dec->i4_max_poc = i4_poc;
 /* IDR Picture or POC wrap around */
 if(i4_poc == 0)
 {
                ps_dec->i4_prev_max_display_seq =
                                ps_dec->i4_prev_max_display_seq
 + ps_dec->i4_max_poc
 + ps_dec->u1_max_dec_frame_buffering
 + 1;
                ps_dec->i4_max_poc = 0;
 }

            ps_cur_slice->u1_mmco_equalto5 = 0;
            ps_cur_slice->u2_frame_num = u4_next_frm_num;
 }

 if(ps_dpb_mgr->i1_poc_buf_id_entries
 >= ps_dec->u1_max_dec_frame_buffering)
 {
            ret = ih264d_assign_display_seq(ps_dec);
 if(ret != OK)
 return ret;
 }

        ret = ih264d_insert_pic_in_display_list(
                        ps_dec->ps_dpb_mgr, (WORD8) DO_NOT_DISP,
 (WORD32)(ps_dec->i4_prev_max_display_seq + i4_poc),
                        u4_next_frm_num);
 if(ret != OK)
 return ret;

        pi1_gaps_per_seq[i1_gap_idx]++;
        ret = ih264d_do_mmco_for_gaps(ps_dpb_mgr,
                                ps_dec->ps_cur_sps->u1_num_ref_frames);
 if(ret != OK)
 return ret;

        ih264d_delete_nonref_nondisplay_pics(ps_dpb_mgr);

        u4_next_frm_num++;
 if(u4_next_frm_num >= u4_max_frm_num)
 {
            u4_next_frm_num -= u4_max_frm_num;
 }

        i4_frame_gaps++;
 }

 return OK;
}

A remote code execution vulnerability in libavc in Mediaserver could enable an attacker using a specially crafted file to cause memory corruption during media file and data processing. This issue is rated as Critical due to the possibility of remote code execution within the context of the Mediaserver process. Product: Android. Versions: 6.0, 6.0.1, 7.0, 7.1.1, 7.1.2. Android ID: A-34097672.


WORD32 ih264d_decode_gaps_in_frame_num(dec_struct_t *ps_dec,
                                       UWORD16 u2_frame_num)
{
    UWORD32 u4_next_frm_num, u4_start_frm_num;
    UWORD32 u4_max_frm_num;
 pocstruct_t s_tmp_poc;
    WORD32 i4_poc;
 dec_slice_params_t *ps_cur_slice;

 dec_pic_params_t *ps_pic_params;
    WORD8 i1_gap_idx;
    WORD32 *i4_gaps_start_frm_num;
 dpb_manager_t *ps_dpb_mgr;
    WORD32 i4_frame_gaps;
    WORD8 *pi1_gaps_per_seq;
    WORD32 ret;

    ps_cur_slice = ps_dec->ps_cur_slice;
 if(ps_cur_slice->u1_field_pic_flag)
 {
 if(ps_dec->u2_prev_ref_frame_num == u2_frame_num)
 return 0;
 }

    u4_next_frm_num = ps_dec->u2_prev_ref_frame_num + 1;
    u4_max_frm_num = ps_dec->ps_cur_sps->u2_u4_max_pic_num_minus1 + 1;

 if(u4_next_frm_num >= u4_max_frm_num)
 {
        u4_next_frm_num -= u4_max_frm_num;
 }

 if(u4_next_frm_num == u2_frame_num)
 {
 return (0);
 }

 if((ps_dec->u1_nal_unit_type == IDR_SLICE_NAL)
 && (u4_next_frm_num >= u2_frame_num))
 {
 return (0);
 }
    u4_start_frm_num = u4_next_frm_num;

    s_tmp_poc.i4_pic_order_cnt_lsb = 0;
    s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0;
    s_tmp_poc.i4_pic_order_cnt_lsb = 0;
    s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0;
    s_tmp_poc.i4_delta_pic_order_cnt[0] = 0;
    s_tmp_poc.i4_delta_pic_order_cnt[1] = 0;

     ps_cur_slice = ps_dec->ps_cur_slice;
     ps_pic_params = ps_dec->ps_cur_pps;

     i4_frame_gaps = 0;
     ps_dpb_mgr = ps_dec->ps_dpb_mgr;

 /* Find a empty slot to store gap seqn info */
    i4_gaps_start_frm_num = ps_dpb_mgr->ai4_gaps_start_frm_num;
 for(i1_gap_idx = 0; i1_gap_idx < MAX_FRAMES; i1_gap_idx++)
 {
 if(INVALID_FRAME_NUM == i4_gaps_start_frm_num[i1_gap_idx])
 break;
 }
 if(MAX_FRAMES == i1_gap_idx)
 {
        UWORD32 i4_error_code;
        i4_error_code = ERROR_DBP_MANAGER_T;
 return i4_error_code;
 }

    i4_poc = 0;
    i4_gaps_start_frm_num[i1_gap_idx] = u4_start_frm_num;
    ps_dpb_mgr->ai4_gaps_end_frm_num[i1_gap_idx] = u2_frame_num - 1;
    pi1_gaps_per_seq = ps_dpb_mgr->ai1_gaps_per_seq;
    pi1_gaps_per_seq[i1_gap_idx] = 0;
 while(u4_next_frm_num != u2_frame_num)
 {
        ih264d_delete_nonref_nondisplay_pics(ps_dpb_mgr);
 if(ps_pic_params->ps_sps->u1_pic_order_cnt_type)
 {
 /* allocate a picture buffer and insert it as ST node */
            ret = ih264d_decode_pic_order_cnt(0, u4_next_frm_num,
 &ps_dec->s_prev_pic_poc,
 &s_tmp_poc, ps_cur_slice,
                                              ps_pic_params, 1, 0, 0,
 &i4_poc);
 if(ret != OK)
 return ret;

 /* Display seq no calculations */
 if(i4_poc >= ps_dec->i4_max_poc)
                ps_dec->i4_max_poc = i4_poc;
 /* IDR Picture or POC wrap around */
 if(i4_poc == 0)
 {
                ps_dec->i4_prev_max_display_seq =
                                ps_dec->i4_prev_max_display_seq
 + ps_dec->i4_max_poc
 + ps_dec->u1_max_dec_frame_buffering
 + 1;
                ps_dec->i4_max_poc = 0;
 }

            ps_cur_slice->u1_mmco_equalto5 = 0;
            ps_cur_slice->u2_frame_num = u4_next_frm_num;
 }

 if(ps_dpb_mgr->i1_poc_buf_id_entries
 >= ps_dec->u1_max_dec_frame_buffering)
 {
            ret = ih264d_assign_display_seq(ps_dec);
 if(ret != OK)
 return ret;
 }

        ret = ih264d_insert_pic_in_display_list(
                        ps_dec->ps_dpb_mgr, (WORD8) DO_NOT_DISP,
 (WORD32)(ps_dec->i4_prev_max_display_seq + i4_poc),
                        u4_next_frm_num);
 if(ret != OK)
 return ret;

        pi1_gaps_per_seq[i1_gap_idx]++;
        ret = ih264d_do_mmco_for_gaps(ps_dpb_mgr,
                                ps_dec->ps_cur_sps->u1_num_ref_frames);
 if(ret != OK)
 return ret;

        ih264d_delete_nonref_nondisplay_pics(ps_dpb_mgr);

        u4_next_frm_num++;
 if(u4_next_frm_num >= u4_max_frm_num)
 {
            u4_next_frm_num -= u4_max_frm_num;
 }

        i4_frame_gaps++;
 }

 return OK;
}


IMPEG2D_ERROR_CODES_T impeg2d_vld_decode(
 dec_state_t *ps_dec,
    WORD16      *pi2_outAddr, /*!< Address where decoded symbols will be stored */
 const UWORD8 *pu1_scan, /*!< Scan table to be used */
    UWORD8      *pu1_pos, /*!< Scan table to be used */
    UWORD16     u2_intra_flag, /*!< Intra Macroblock or not */
    UWORD16     u2_chroma_flag, /*!< Chroma Block or not */
    UWORD16     u2_d_picture, /*!< D Picture or not */
    UWORD16     u2_intra_vlc_format, /*!< Intra VLC format */
    UWORD16     u2_mpeg2, /*!< MPEG-2 or not */
    WORD32      *pi4_num_coeffs /*!< Returns the number of coeffs in block */
 )
{

    UWORD32 u4_sym_len;

    UWORD32 u4_decoded_value;
    UWORD32 u4_level_first_byte;
    WORD32  u4_level;
    UWORD32 u4_run, u4_numCoeffs;
    UWORD32 u4_buf;
    UWORD32 u4_buf_nxt;
    UWORD32 u4_offset;
    UWORD32 *pu4_buf_aligned;
    UWORD32 u4_bits;
 stream_t *ps_stream = &ps_dec->s_bit_stream;
    WORD32  u4_pos;
    UWORD32 u4_nz_cols;
    UWORD32 u4_nz_rows;

 *pi4_num_coeffs = 0;

    ps_dec->u4_non_zero_cols = 0;
    ps_dec->u4_non_zero_rows = 0;
    u4_nz_cols = ps_dec->u4_non_zero_cols;
    u4_nz_rows = ps_dec->u4_non_zero_rows;

    GET_TEMP_STREAM_DATA(u4_buf,u4_buf_nxt,u4_offset,pu4_buf_aligned,ps_stream)
 /**************************************************************************/
 /* Decode the DC coefficient in case of Intra block                       */
 /**************************************************************************/
 if(u2_intra_flag)
 {
        WORD32 dc_size;
        WORD32 dc_diff;
        WORD32 maxLen;
        WORD32 idx;

        maxLen = MPEG2_DCT_DC_SIZE_LEN;
        idx = 0;
 if(u2_chroma_flag != 0)
 {
            maxLen += 1;
            idx++;
 }

 {
            WORD16  end = 0;
            UWORD32 maxLen_tmp = maxLen;
            UWORD16 m_iBit;

 /* Get the maximum number of bits needed to decode a symbol */
            IBITS_NXT(u4_buf,u4_buf_nxt,u4_offset,u4_bits,maxLen)
 do
 {
                maxLen_tmp--;
 /* Read one bit at a time from the variable to decode the huffman code */
                m_iBit = (UWORD8)((u4_bits >> maxLen_tmp) & 0x1);

 /* Get the next node pointer or the symbol from the tree */
                end = gai2_impeg2d_dct_dc_size[idx][end][m_iBit];
 }while(end > 0);
            dc_size = end + MPEG2_DCT_DC_SIZE_OFFSET;

 /* Flush the appropriate number of bits from the stream */
            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,(maxLen - maxLen_tmp),pu4_buf_aligned)

 }

 if (dc_size != 0)
 {
            UWORD32 u4_bits;

            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned, dc_size)
            dc_diff = u4_bits;

 if ((dc_diff & (1 << (dc_size - 1))) == 0) //v Probably the prediction algo?
                dc_diff -= (1 << dc_size) - 1;
 }
 else
 {
            dc_diff = 0;
 }

        pi2_outAddr[*pi4_num_coeffs] = dc_diff;
 /* This indicates the position of the coefficient. Since this is the DC
         * coefficient, we put the position as 0.
         */
        pu1_pos[*pi4_num_coeffs] = pu1_scan[0];
 (*pi4_num_coeffs)++;

 if (0 != dc_diff)
 {
            u4_nz_cols |= 0x01;
            u4_nz_rows |= 0x01;
 }

        u4_numCoeffs = 1;
 }
 /**************************************************************************/
 /* Decoding of first AC coefficient in case of non Intra block            */
 /**************************************************************************/
 else
 {
 /* First symbol can be 1s */
        UWORD32 u4_bits;

        IBITS_NXT(u4_buf,u4_buf_nxt,u4_offset,u4_bits,1)

 if(u4_bits == 1)
 {

            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,1, pu4_buf_aligned)
            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned, 1)
 if(u4_bits == 1)
 {
                pi2_outAddr[*pi4_num_coeffs] = -1;
 }
 else
 {
                pi2_outAddr[*pi4_num_coeffs] = 1;
 }

 /* This indicates the position of the coefficient. Since this is the DC
             * coefficient, we put the position as 0.
             */
            pu1_pos[*pi4_num_coeffs] = pu1_scan[0];
 (*pi4_num_coeffs)++;
            u4_numCoeffs = 1;

            u4_nz_cols |= 0x01;
            u4_nz_rows |= 0x01;
 }
 else
 {
            u4_numCoeffs = 0;
 }
 }
 if (1 == u2_d_picture)
 {
        PUT_TEMP_STREAM_DATA(u4_buf, u4_buf_nxt, u4_offset, pu4_buf_aligned, ps_stream)
        ps_dec->u4_non_zero_cols  = u4_nz_cols;
        ps_dec->u4_non_zero_rows  = u4_nz_rows;
 return ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE);
 }

 if (1 == u2_intra_vlc_format && u2_intra_flag)
 {

 while(1)
 {

                UWORD32 lead_zeros;
                WORD16 DecodedValue;

                 u4_sym_len = 17;
                 IBITS_NXT(u4_buf,u4_buf_nxt,u4_offset,u4_bits,u4_sym_len)

                 DecodedValue = gau2_impeg2d_tab_one_1_9[u4_bits >> 8];
                 u4_sym_len = (DecodedValue & 0xf);
                 u4_level = DecodedValue >> 9;
 /* One table lookup */
 if(0 != u4_level)
 {
                    u4_run = ((DecodedValue >> 4) & 0x1f);
                    u4_numCoeffs       += u4_run;
                    u4_pos             = pu1_scan[u4_numCoeffs++ & 63];
                    pu1_pos[*pi4_num_coeffs] = u4_pos;

                    FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                    pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 else
 {
 if (DecodedValue == END_OF_BLOCK_ONE)
 {
                        u4_sym_len = 4;

 break;
 }
 else
 {
 /*Second table lookup*/
                        lead_zeros = CLZ(u4_bits) - 20;/* -16 since we are dealing with WORD32 */
 if (0 != lead_zeros)
 {

                            u4_bits         = (u4_bits >> (6 - lead_zeros)) & 0x001F;

 /* Flush the number of bits */
 if (1 == lead_zeros)
 {
                                u4_sym_len         = ((u4_bits & 0x18) >> 3) == 2 ? 11:10;
 }
 else
 {
                                u4_sym_len         = 11 + lead_zeros;
 }
 /* flushing */
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)

 /* Calculate the address */
                            u4_bits         = ((lead_zeros - 1) << 5) + u4_bits;

 DecodedValue = gau2_impeg2d_tab_one_10_16[u4_bits];

                            u4_run = BITS(DecodedValue, 8,4);
                            u4_level = ((WORD16) DecodedValue) >> 9;

                            u4_numCoeffs       += u4_run;
                            u4_pos             = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 /*********************************************************************/
 /* MPEG2 Escape Code                                                 */
 /*********************************************************************/
 else if(u2_mpeg2 == 1)
 {
                            u4_sym_len         = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,18)
                                u4_decoded_value    = u4_bits;
                            u4_run             = (u4_decoded_value >> 12);
                            u4_level           = (u4_decoded_value & 0x0FFF);

 if (u4_level)
                                u4_level = (u4_level - ((u4_level & 0x0800) << 1));

                            u4_numCoeffs       += u4_run;
                            u4_pos             = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 /*********************************************************************/
 /* MPEG1 Escape Code                                                 */
 /*********************************************************************/
 else
 {
 /*-----------------------------------------------------------
                            * MPEG-1 Stream
                            *
                            * <See D.9.3 of MPEG-2> Run-level escape syntax
                            * Run-level values that cannot be coded with a VLC are coded
                            * by the escape code '0000 01' followed by
                            * either a 14-bit FLC (127 <= level <= 127),
                            * or a 22-bit FLC (255 <= level <= 255).
                            * This is described in Annex B,B.5f of MPEG-1.standard
                            *-----------------------------------------------------------*/

 /*-----------------------------------------------------------
                            * First 6 bits are the value of the Run. Next is First 8 bits
                            * of Level. These bits decide whether it is 14 bit FLC or
                            * 22-bit FLC.
                            *
                            * If( first 8 bits of Level == '1000000' or '00000000')
                            *      then its is 22-bit FLC.
                            * else
                            *      it is 14-bit FLC.
                            *-----------------------------------------------------------*/
                            u4_sym_len         = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,14)
                                u4_decoded_value     = u4_bits;
                            u4_run              = (u4_decoded_value >> 8);
                            u4_level_first_byte = (u4_decoded_value & 0x0FF);
 if(u4_level_first_byte & 0x7F)
 {
 /*-------------------------------------------------------
                                * First 8 bits of level are neither 1000000 nor 00000000
                                * Hence 14-bit FLC (Last 8 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_First_Byte - 256 : Level_First_Byte
                                *-------------------------------------------------------*/
                                u4_level = (u4_level_first_byte -
 ((u4_level_first_byte & 0x80) << 1));
 }
 else
 {
 /*-------------------------------------------------------
                                * Next 8 bits are either 1000000 or 00000000
                                * Hence 22-bit FLC (Last 16 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_Second_Byte - 256 : Level_Second_Byte
                                *-------------------------------------------------------*/
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,8)
                                    u4_level = u4_bits;
                                u4_level = (u4_level - (u4_level_first_byte << 1));
 }
                            u4_numCoeffs += u4_run;

                            u4_pos = pu1_scan[u4_numCoeffs++ & 63];

                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 }
 }

                u4_nz_cols |= 1 << (u4_pos & 0x7);
                u4_nz_rows |= 1 << (u4_pos >> 0x3);

 if (u4_numCoeffs > 64)
 {
 return IMPEG2D_MB_TEX_DECODE_ERR;
 }

 }
            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,u4_sym_len)
 }
 else
 {
 while(1)
 {

                UWORD32 lead_zeros;
                UWORD16 DecodedValue;

                 u4_sym_len = 17;
                 IBITS_NXT(u4_buf, u4_buf_nxt, u4_offset, u4_bits, u4_sym_len)

                 DecodedValue = gau2_impeg2d_tab_zero_1_9[u4_bits >> 8];
                 u4_sym_len = BITS(DecodedValue, 3, 0);
                u4_level = ((WORD16) DecodedValue) >> 9;

 if (0 != u4_level)
 {
                    u4_run = BITS(DecodedValue, 8,4);

                    u4_numCoeffs       += u4_run;

                    u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                    pu1_pos[*pi4_num_coeffs] = u4_pos;

                    FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                    pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 else
 {
 if(DecodedValue == END_OF_BLOCK_ZERO)
 {
                        u4_sym_len = 2;

 break;
 }
 else
 {
                        lead_zeros = CLZ(u4_bits) - 20;/* -15 since we are dealing with WORD32 */
 /*Second table lookup*/
 if (0 != lead_zeros)
 {
                            u4_bits         = (u4_bits >> (6 - lead_zeros)) & 0x001F;

 /* Flush the number of bits */
                            u4_sym_len         = 11 + lead_zeros;

 /* Calculate the address */
                            u4_bits         = ((lead_zeros - 1) << 5) + u4_bits;

 DecodedValue = gau2_impeg2d_tab_zero_10_16[u4_bits];

                            u4_run = BITS(DecodedValue, 8,4);
                            u4_level = ((WORD16) DecodedValue) >> 9;

                            u4_numCoeffs       += u4_run;

                            u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
 if (1 == lead_zeros)
                                u4_sym_len--;
 /* flushing */
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 /*Escape Sequence*/
 else if(u2_mpeg2 == 1)
 {
                            u4_sym_len         = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,18)
                            u4_decoded_value    = u4_bits;
                            u4_run             = (u4_decoded_value >> 12);
                            u4_level           = (u4_decoded_value & 0x0FFF);

 if (u4_level)
                                u4_level = (u4_level - ((u4_level & 0x0800) << 1));

                            u4_numCoeffs           += u4_run;

                            u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 /*********************************************************************/
 /* MPEG1 Escape Code                                                 */
 /*********************************************************************/
 else
 {
 /*-----------------------------------------------------------
                            * MPEG-1 Stream
                            *
                            * <See D.9.3 of MPEG-2> Run-level escape syntax
                            * Run-level values that cannot be coded with a VLC are coded
                            * by the escape code '0000 01' followed by
                            * either a 14-bit FLC (127 <= level <= 127),
                            * or a 22-bit FLC (255 <= level <= 255).
                            * This is described in Annex B,B.5f of MPEG-1.standard
                            *-----------------------------------------------------------*/

 /*-----------------------------------------------------------
                            * First 6 bits are the value of the Run. Next is First 8 bits
                            * of Level. These bits decide whether it is 14 bit FLC or
                            * 22-bit FLC.
                            *
                            * If( first 8 bits of Level == '1000000' or '00000000')
                            *      then its is 22-bit FLC.
                            * else
                            *      it is 14-bit FLC.
                            *-----------------------------------------------------------*/
                            u4_sym_len             = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,14)
                            u4_decoded_value        = u4_bits;
                            u4_run                 = (u4_decoded_value >> 8);
                            u4_level_first_byte    = (u4_decoded_value & 0x0FF);
 if(u4_level_first_byte & 0x7F)
 {
 /*-------------------------------------------------------
                                * First 8 bits of level are neither 1000000 nor 00000000
                                * Hence 14-bit FLC (Last 8 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_First_Byte - 256 : Level_First_Byte
                                *-------------------------------------------------------*/
                                u4_level = (u4_level_first_byte -
 ((u4_level_first_byte & 0x80) << 1));
 }
 else
 {
 /*-------------------------------------------------------
                                * Next 8 bits are either 1000000 or 00000000
                                * Hence 22-bit FLC (Last 16 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_Second_Byte - 256 : Level_Second_Byte
                                *-------------------------------------------------------*/
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,8)
                                u4_level = u4_bits;
                                u4_level = (u4_level - (u4_level_first_byte << 1));
 }
                            u4_numCoeffs           += u4_run;

                            u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 }
 }

                u4_nz_cols |= 1 << (u4_pos & 0x7);
                u4_nz_rows |= 1 << (u4_pos >> 0x3);
 if (u4_numCoeffs > 64)
 {
 return IMPEG2D_MB_TEX_DECODE_ERR;
 }

 }

            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,u4_sym_len)

 }

        PUT_TEMP_STREAM_DATA(u4_buf, u4_buf_nxt, u4_offset, pu4_buf_aligned, ps_stream)

        ps_dec->u4_non_zero_cols  = u4_nz_cols;
        ps_dec->u4_non_zero_rows  = u4_nz_rows;

 return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
}

An information disclosure vulnerability in libmpeg2 in Mediaserver could enable a local malicious application to access data outside of its permission levels. This issue is rated as Moderate because it could be used to access data without permission. Product: Android. Versions: 6.0, 6.0.1, 7.0, 7.1.1. Android ID: A-34093073.


IMPEG2D_ERROR_CODES_T impeg2d_vld_decode(
 dec_state_t *ps_dec,
    WORD16      *pi2_outAddr, /*!< Address where decoded symbols will be stored */
 const UWORD8 *pu1_scan, /*!< Scan table to be used */
    UWORD8      *pu1_pos, /*!< Scan table to be used */
    UWORD16     u2_intra_flag, /*!< Intra Macroblock or not */
    UWORD16     u2_chroma_flag, /*!< Chroma Block or not */
    UWORD16     u2_d_picture, /*!< D Picture or not */
    UWORD16     u2_intra_vlc_format, /*!< Intra VLC format */
    UWORD16     u2_mpeg2, /*!< MPEG-2 or not */
    WORD32      *pi4_num_coeffs /*!< Returns the number of coeffs in block */
 )
{

    UWORD32 u4_sym_len;

    UWORD32 u4_decoded_value;
    UWORD32 u4_level_first_byte;
    WORD32  u4_level;
    UWORD32 u4_run, u4_numCoeffs;
    UWORD32 u4_buf;
    UWORD32 u4_buf_nxt;
    UWORD32 u4_offset;
    UWORD32 *pu4_buf_aligned;
    UWORD32 u4_bits;
 stream_t *ps_stream = &ps_dec->s_bit_stream;
    WORD32  u4_pos;
    UWORD32 u4_nz_cols;
    UWORD32 u4_nz_rows;

 *pi4_num_coeffs = 0;

    ps_dec->u4_non_zero_cols = 0;
    ps_dec->u4_non_zero_rows = 0;
    u4_nz_cols = ps_dec->u4_non_zero_cols;
    u4_nz_rows = ps_dec->u4_non_zero_rows;

    GET_TEMP_STREAM_DATA(u4_buf,u4_buf_nxt,u4_offset,pu4_buf_aligned,ps_stream)
 /**************************************************************************/
 /* Decode the DC coefficient in case of Intra block                       */
 /**************************************************************************/
 if(u2_intra_flag)
 {
        WORD32 dc_size;
        WORD32 dc_diff;
        WORD32 maxLen;
        WORD32 idx;

        maxLen = MPEG2_DCT_DC_SIZE_LEN;
        idx = 0;
 if(u2_chroma_flag != 0)
 {
            maxLen += 1;
            idx++;
 }

 {
            WORD16  end = 0;
            UWORD32 maxLen_tmp = maxLen;
            UWORD16 m_iBit;

 /* Get the maximum number of bits needed to decode a symbol */
            IBITS_NXT(u4_buf,u4_buf_nxt,u4_offset,u4_bits,maxLen)
 do
 {
                maxLen_tmp--;
 /* Read one bit at a time from the variable to decode the huffman code */
                m_iBit = (UWORD8)((u4_bits >> maxLen_tmp) & 0x1);

 /* Get the next node pointer or the symbol from the tree */
                end = gai2_impeg2d_dct_dc_size[idx][end][m_iBit];
 }while(end > 0);
            dc_size = end + MPEG2_DCT_DC_SIZE_OFFSET;

 /* Flush the appropriate number of bits from the stream */
            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,(maxLen - maxLen_tmp),pu4_buf_aligned)

 }

 if (dc_size != 0)
 {
            UWORD32 u4_bits;

            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned, dc_size)
            dc_diff = u4_bits;

 if ((dc_diff & (1 << (dc_size - 1))) == 0) //v Probably the prediction algo?
                dc_diff -= (1 << dc_size) - 1;
 }
 else
 {
            dc_diff = 0;
 }

        pi2_outAddr[*pi4_num_coeffs] = dc_diff;
 /* This indicates the position of the coefficient. Since this is the DC
         * coefficient, we put the position as 0.
         */
        pu1_pos[*pi4_num_coeffs] = pu1_scan[0];
 (*pi4_num_coeffs)++;

 if (0 != dc_diff)
 {
            u4_nz_cols |= 0x01;
            u4_nz_rows |= 0x01;
 }

        u4_numCoeffs = 1;
 }
 /**************************************************************************/
 /* Decoding of first AC coefficient in case of non Intra block            */
 /**************************************************************************/
 else
 {
 /* First symbol can be 1s */
        UWORD32 u4_bits;

        IBITS_NXT(u4_buf,u4_buf_nxt,u4_offset,u4_bits,1)

 if(u4_bits == 1)
 {

            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,1, pu4_buf_aligned)
            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned, 1)
 if(u4_bits == 1)
 {
                pi2_outAddr[*pi4_num_coeffs] = -1;
 }
 else
 {
                pi2_outAddr[*pi4_num_coeffs] = 1;
 }

 /* This indicates the position of the coefficient. Since this is the DC
             * coefficient, we put the position as 0.
             */
            pu1_pos[*pi4_num_coeffs] = pu1_scan[0];
 (*pi4_num_coeffs)++;
            u4_numCoeffs = 1;

            u4_nz_cols |= 0x01;
            u4_nz_rows |= 0x01;
 }
 else
 {
            u4_numCoeffs = 0;
 }
 }
 if (1 == u2_d_picture)
 {
        PUT_TEMP_STREAM_DATA(u4_buf, u4_buf_nxt, u4_offset, pu4_buf_aligned, ps_stream)
        ps_dec->u4_non_zero_cols  = u4_nz_cols;
        ps_dec->u4_non_zero_rows  = u4_nz_rows;
 return ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE);
 }

 if (1 == u2_intra_vlc_format && u2_intra_flag)
 {

 while(1)
 {

                UWORD32 lead_zeros;
                WORD16 DecodedValue;

                 u4_sym_len = 17;
                 IBITS_NXT(u4_buf,u4_buf_nxt,u4_offset,u4_bits,u4_sym_len)

                /* There cannot be more than 11 leading zeros in the decoded
                 * symbol. The symbol is only 17 bits long, so we subtract 15.
                 */
                lead_zeros = CLZ(u4_bits) - 15;
                if (lead_zeros > 11)
                {
                    return IMPEG2D_MB_DATA_DECODE_ERR;
                }

                 DecodedValue = gau2_impeg2d_tab_one_1_9[u4_bits >> 8];
                 u4_sym_len = (DecodedValue & 0xf);
                 u4_level = DecodedValue >> 9;
 /* One table lookup */
 if(0 != u4_level)
 {
                    u4_run = ((DecodedValue >> 4) & 0x1f);
                    u4_numCoeffs       += u4_run;
                    u4_pos             = pu1_scan[u4_numCoeffs++ & 63];
                    pu1_pos[*pi4_num_coeffs] = u4_pos;

                    FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                    pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 else
 {
 if (DecodedValue == END_OF_BLOCK_ONE)
 {
                        u4_sym_len = 4;

 break;
 }
 else
 {
 /*Second table lookup*/
                        lead_zeros = CLZ(u4_bits) - 20;/* -16 since we are dealing with WORD32 */
 if (0 != lead_zeros)
 {

                            u4_bits         = (u4_bits >> (6 - lead_zeros)) & 0x001F;

 /* Flush the number of bits */
 if (1 == lead_zeros)
 {
                                u4_sym_len         = ((u4_bits & 0x18) >> 3) == 2 ? 11:10;
 }
 else
 {
                                u4_sym_len         = 11 + lead_zeros;
 }
 /* flushing */
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)

 /* Calculate the address */
                            u4_bits         = ((lead_zeros - 1) << 5) + u4_bits;

 DecodedValue = gau2_impeg2d_tab_one_10_16[u4_bits];

                            u4_run = BITS(DecodedValue, 8,4);
                            u4_level = ((WORD16) DecodedValue) >> 9;

                            u4_numCoeffs       += u4_run;
                            u4_pos             = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 /*********************************************************************/
 /* MPEG2 Escape Code                                                 */
 /*********************************************************************/
 else if(u2_mpeg2 == 1)
 {
                            u4_sym_len         = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,18)
                                u4_decoded_value    = u4_bits;
                            u4_run             = (u4_decoded_value >> 12);
                            u4_level           = (u4_decoded_value & 0x0FFF);

 if (u4_level)
                                u4_level = (u4_level - ((u4_level & 0x0800) << 1));

                            u4_numCoeffs       += u4_run;
                            u4_pos             = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 /*********************************************************************/
 /* MPEG1 Escape Code                                                 */
 /*********************************************************************/
 else
 {
 /*-----------------------------------------------------------
                            * MPEG-1 Stream
                            *
                            * <See D.9.3 of MPEG-2> Run-level escape syntax
                            * Run-level values that cannot be coded with a VLC are coded
                            * by the escape code '0000 01' followed by
                            * either a 14-bit FLC (127 <= level <= 127),
                            * or a 22-bit FLC (255 <= level <= 255).
                            * This is described in Annex B,B.5f of MPEG-1.standard
                            *-----------------------------------------------------------*/

 /*-----------------------------------------------------------
                            * First 6 bits are the value of the Run. Next is First 8 bits
                            * of Level. These bits decide whether it is 14 bit FLC or
                            * 22-bit FLC.
                            *
                            * If( first 8 bits of Level == '1000000' or '00000000')
                            *      then its is 22-bit FLC.
                            * else
                            *      it is 14-bit FLC.
                            *-----------------------------------------------------------*/
                            u4_sym_len         = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,14)
                                u4_decoded_value     = u4_bits;
                            u4_run              = (u4_decoded_value >> 8);
                            u4_level_first_byte = (u4_decoded_value & 0x0FF);
 if(u4_level_first_byte & 0x7F)
 {
 /*-------------------------------------------------------
                                * First 8 bits of level are neither 1000000 nor 00000000
                                * Hence 14-bit FLC (Last 8 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_First_Byte - 256 : Level_First_Byte
                                *-------------------------------------------------------*/
                                u4_level = (u4_level_first_byte -
 ((u4_level_first_byte & 0x80) << 1));
 }
 else
 {
 /*-------------------------------------------------------
                                * Next 8 bits are either 1000000 or 00000000
                                * Hence 22-bit FLC (Last 16 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_Second_Byte - 256 : Level_Second_Byte
                                *-------------------------------------------------------*/
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,8)
                                    u4_level = u4_bits;
                                u4_level = (u4_level - (u4_level_first_byte << 1));
 }
                            u4_numCoeffs += u4_run;

                            u4_pos = pu1_scan[u4_numCoeffs++ & 63];

                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 }
 }

                u4_nz_cols |= 1 << (u4_pos & 0x7);
                u4_nz_rows |= 1 << (u4_pos >> 0x3);

 if (u4_numCoeffs > 64)
 {
 return IMPEG2D_MB_TEX_DECODE_ERR;
 }

 }
            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,u4_sym_len)
 }
 else
 {
 while(1)
 {

                UWORD32 lead_zeros;
                UWORD16 DecodedValue;

                 u4_sym_len = 17;
                 IBITS_NXT(u4_buf, u4_buf_nxt, u4_offset, u4_bits, u4_sym_len)

                /* There cannot be more than 11 leading zeros in the decoded
                 * symbol. The symbol is only 17 bits long, so we subtract 15.
                 */
                lead_zeros = CLZ(u4_bits) - 15;
                if (lead_zeros > 11)
                {
                    return IMPEG2D_MB_DATA_DECODE_ERR;
                }

                 DecodedValue = gau2_impeg2d_tab_zero_1_9[u4_bits >> 8];
                 u4_sym_len = BITS(DecodedValue, 3, 0);
                u4_level = ((WORD16) DecodedValue) >> 9;

 if (0 != u4_level)
 {
                    u4_run = BITS(DecodedValue, 8,4);

                    u4_numCoeffs       += u4_run;

                    u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                    pu1_pos[*pi4_num_coeffs] = u4_pos;

                    FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                    pi2_outAddr[*pi4_num_coeffs] = u4_level;
 (*pi4_num_coeffs)++;
 }
 else
 {
 if(DecodedValue == END_OF_BLOCK_ZERO)
 {
                        u4_sym_len = 2;

 break;
 }
 else
 {
                        lead_zeros = CLZ(u4_bits) - 20;/* -15 since we are dealing with WORD32 */
 /*Second table lookup*/
 if (0 != lead_zeros)
 {
                            u4_bits         = (u4_bits >> (6 - lead_zeros)) & 0x001F;

 /* Flush the number of bits */
                            u4_sym_len         = 11 + lead_zeros;

 /* Calculate the address */
                            u4_bits         = ((lead_zeros - 1) << 5) + u4_bits;

 DecodedValue = gau2_impeg2d_tab_zero_10_16[u4_bits];

                            u4_run = BITS(DecodedValue, 8,4);
                            u4_level = ((WORD16) DecodedValue) >> 9;

                            u4_numCoeffs       += u4_run;

                            u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
 if (1 == lead_zeros)
                                u4_sym_len--;
 /* flushing */
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 /*Escape Sequence*/
 else if(u2_mpeg2 == 1)
 {
                            u4_sym_len         = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,18)
                            u4_decoded_value    = u4_bits;
                            u4_run             = (u4_decoded_value >> 12);
                            u4_level           = (u4_decoded_value & 0x0FFF);

 if (u4_level)
                                u4_level = (u4_level - ((u4_level & 0x0800) << 1));

                            u4_numCoeffs           += u4_run;

                            u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 /*********************************************************************/
 /* MPEG1 Escape Code                                                 */
 /*********************************************************************/
 else
 {
 /*-----------------------------------------------------------
                            * MPEG-1 Stream
                            *
                            * <See D.9.3 of MPEG-2> Run-level escape syntax
                            * Run-level values that cannot be coded with a VLC are coded
                            * by the escape code '0000 01' followed by
                            * either a 14-bit FLC (127 <= level <= 127),
                            * or a 22-bit FLC (255 <= level <= 255).
                            * This is described in Annex B,B.5f of MPEG-1.standard
                            *-----------------------------------------------------------*/

 /*-----------------------------------------------------------
                            * First 6 bits are the value of the Run. Next is First 8 bits
                            * of Level. These bits decide whether it is 14 bit FLC or
                            * 22-bit FLC.
                            *
                            * If( first 8 bits of Level == '1000000' or '00000000')
                            *      then its is 22-bit FLC.
                            * else
                            *      it is 14-bit FLC.
                            *-----------------------------------------------------------*/
                            u4_sym_len             = 6;
                            FLUSH_BITS(u4_offset,u4_buf,u4_buf_nxt,u4_sym_len,pu4_buf_aligned)
                            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,14)
                            u4_decoded_value        = u4_bits;
                            u4_run                 = (u4_decoded_value >> 8);
                            u4_level_first_byte    = (u4_decoded_value & 0x0FF);
 if(u4_level_first_byte & 0x7F)
 {
 /*-------------------------------------------------------
                                * First 8 bits of level are neither 1000000 nor 00000000
                                * Hence 14-bit FLC (Last 8 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_First_Byte - 256 : Level_First_Byte
                                *-------------------------------------------------------*/
                                u4_level = (u4_level_first_byte -
 ((u4_level_first_byte & 0x80) << 1));
 }
 else
 {
 /*-------------------------------------------------------
                                * Next 8 bits are either 1000000 or 00000000
                                * Hence 22-bit FLC (Last 16 bits are used to get level)
                                *
                                *  Level = (msb of Level_First_Byte is 1)?
                                *          Level_Second_Byte - 256 : Level_Second_Byte
                                *-------------------------------------------------------*/
                                IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,8)
                                u4_level = u4_bits;
                                u4_level = (u4_level - (u4_level_first_byte << 1));
 }
                            u4_numCoeffs           += u4_run;

                            u4_pos                 = pu1_scan[u4_numCoeffs++ & 63];
                            pu1_pos[*pi4_num_coeffs] = u4_pos;
                            pi2_outAddr[*pi4_num_coeffs] = u4_level;

 (*pi4_num_coeffs)++;
 }
 }
 }

                u4_nz_cols |= 1 << (u4_pos & 0x7);
                u4_nz_rows |= 1 << (u4_pos >> 0x3);
 if (u4_numCoeffs > 64)
 {
 return IMPEG2D_MB_TEX_DECODE_ERR;
 }

 }

            IBITS_GET(u4_buf,u4_buf_nxt,u4_offset,u4_bits,pu4_buf_aligned,u4_sym_len)

 }

        PUT_TEMP_STREAM_DATA(u4_buf, u4_buf_nxt, u4_offset, pu4_buf_aligned, ps_stream)

        ps_dec->u4_non_zero_cols  = u4_nz_cols;
        ps_dec->u4_non_zero_rows  = u4_nz_rows;

 return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
}


IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_hdr(dec_state_t *ps_dec)
{
 stream_t *ps_stream;
    ps_stream = &ps_dec->s_bit_stream;
    UWORD16 u2_height;
    UWORD16 u2_width;

 if (impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) != SEQUENCE_HEADER_CODE)
 {
        impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
 return IMPEG2D_FRM_HDR_START_CODE_NOT_FOUND;

 }
    impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);

    u2_width    = impeg2d_bit_stream_get(ps_stream,12);
    u2_height   = impeg2d_bit_stream_get(ps_stream,12);

 if ((u2_width != ps_dec->u2_horizontal_size)
 || (u2_height != ps_dec->u2_vertical_size))
 {
 if (0 == ps_dec->u2_header_done)
 {
 /* This is the first time we are reading the resolution */
            ps_dec->u2_horizontal_size = u2_width;
            ps_dec->u2_vertical_size = u2_height;
 if (0 == ps_dec->u4_frm_buf_stride)
 {
                ps_dec->u4_frm_buf_stride  = (UWORD32) ALIGN16(u2_width);
 }
 }
 else
 {
 if((u2_width > ps_dec->u2_create_max_width)
 || (u2_height > ps_dec->u2_create_max_height))
 {
                IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS;

                ps_dec->u2_reinit_max_height   = u2_height;
                ps_dec->u2_reinit_max_width    = u2_width;

 return e_error;
 }
 else
 {
 /* The resolution has changed */
 return (IMPEG2D_ERROR_CODES_T)IVD_RES_CHANGED;
 }
 }
 }

 if((ps_dec->u2_horizontal_size > ps_dec->u2_create_max_width)
 || (ps_dec->u2_vertical_size > ps_dec->u2_create_max_height))
 {
        IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS;
 return SET_IVD_FATAL_ERROR(e_error);
 }

 /*------------------------------------------------------------------------*/
 /* Flush the following as they are not being used                         */
 /* aspect_ratio_info (4 bits)                                             */
 /*------------------------------------------------------------------------*/
    ps_dec->u2_aspect_ratio_info = impeg2d_bit_stream_get(ps_stream,4);

 /*------------------------------------------------------------------------*/

     /* Frame rate code(4 bits)                                                */
     /*------------------------------------------------------------------------*/
     ps_dec->u2_frame_rate_code = impeg2d_bit_stream_get(ps_stream,4);
     /*------------------------------------------------------------------------*/
     /* Flush the following as they are not being used                         */
     /* bit_rate_value (18 bits)                                               */
 /*------------------------------------------------------------------------*/
    impeg2d_bit_stream_flush(ps_stream,18);
    GET_MARKER_BIT(ps_dec,ps_stream);
 /*------------------------------------------------------------------------*/
 /* Flush the following as they are not being used                         */
 /* vbv_buffer_size_value(10 bits), constrained_parameter_flag (1 bit)     */
 /*------------------------------------------------------------------------*/
    impeg2d_bit_stream_flush(ps_stream,11);

 /*------------------------------------------------------------------------*/
 /* Quantization matrix for the intra blocks                               */
 /*------------------------------------------------------------------------*/
 if(impeg2d_bit_stream_get_bit(ps_stream) == 1)
 {
        UWORD16 i;
 for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
 {
            ps_dec->au1_intra_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
 }

 }
 else
 {
        memcpy(ps_dec->au1_intra_quant_matrix,gau1_impeg2_intra_quant_matrix_default,
                NUM_PELS_IN_BLOCK);
 }

 /*------------------------------------------------------------------------*/
 /* Quantization matrix for the inter blocks                               */
 /*------------------------------------------------------------------------*/
 if(impeg2d_bit_stream_get_bit(ps_stream) == 1)
 {
        UWORD16 i;
 for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
 {
            ps_dec->au1_inter_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
 }
 }
 else
 {
        memcpy(ps_dec->au1_inter_quant_matrix,gau1_impeg2_inter_quant_matrix_default,
            NUM_PELS_IN_BLOCK);
 }
    impeg2d_next_start_code(ps_dec);

 return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
}

An information disclosure vulnerability in libmpeg2 in Mediaserver could enable a local malicious application to access data outside of its permission levels. This issue is rated as Moderate because it could be used to access data without permission. Product: Android. Versions: 6.0, 6.0.1, 7.0, 7.1.1. Android ID: A-34093952.


IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_hdr(dec_state_t *ps_dec)
{
 stream_t *ps_stream;
    ps_stream = &ps_dec->s_bit_stream;
    UWORD16 u2_height;
    UWORD16 u2_width;

 if (impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) != SEQUENCE_HEADER_CODE)
 {
        impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
 return IMPEG2D_FRM_HDR_START_CODE_NOT_FOUND;

 }
    impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);

    u2_width    = impeg2d_bit_stream_get(ps_stream,12);
    u2_height   = impeg2d_bit_stream_get(ps_stream,12);

 if ((u2_width != ps_dec->u2_horizontal_size)
 || (u2_height != ps_dec->u2_vertical_size))
 {
 if (0 == ps_dec->u2_header_done)
 {
 /* This is the first time we are reading the resolution */
            ps_dec->u2_horizontal_size = u2_width;
            ps_dec->u2_vertical_size = u2_height;
 if (0 == ps_dec->u4_frm_buf_stride)
 {
                ps_dec->u4_frm_buf_stride  = (UWORD32) ALIGN16(u2_width);
 }
 }
 else
 {
 if((u2_width > ps_dec->u2_create_max_width)
 || (u2_height > ps_dec->u2_create_max_height))
 {
                IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS;

                ps_dec->u2_reinit_max_height   = u2_height;
                ps_dec->u2_reinit_max_width    = u2_width;

 return e_error;
 }
 else
 {
 /* The resolution has changed */
 return (IMPEG2D_ERROR_CODES_T)IVD_RES_CHANGED;
 }
 }
 }

 if((ps_dec->u2_horizontal_size > ps_dec->u2_create_max_width)
 || (ps_dec->u2_vertical_size > ps_dec->u2_create_max_height))
 {
        IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS;
 return SET_IVD_FATAL_ERROR(e_error);
 }

 /*------------------------------------------------------------------------*/
 /* Flush the following as they are not being used                         */
 /* aspect_ratio_info (4 bits)                                             */
 /*------------------------------------------------------------------------*/
    ps_dec->u2_aspect_ratio_info = impeg2d_bit_stream_get(ps_stream,4);

 /*------------------------------------------------------------------------*/

     /* Frame rate code(4 bits)                                                */
     /*------------------------------------------------------------------------*/
     ps_dec->u2_frame_rate_code = impeg2d_bit_stream_get(ps_stream,4);
    if (ps_dec->u2_frame_rate_code > MPEG2_MAX_FRAME_RATE_CODE)
    {
        return IMPEG2D_FRM_HDR_DECODE_ERR;
    }
     /*------------------------------------------------------------------------*/
     /* Flush the following as they are not being used                         */
     /* bit_rate_value (18 bits)                                               */
 /*------------------------------------------------------------------------*/
    impeg2d_bit_stream_flush(ps_stream,18);
    GET_MARKER_BIT(ps_dec,ps_stream);
 /*------------------------------------------------------------------------*/
 /* Flush the following as they are not being used                         */
 /* vbv_buffer_size_value(10 bits), constrained_parameter_flag (1 bit)     */
 /*------------------------------------------------------------------------*/
    impeg2d_bit_stream_flush(ps_stream,11);

 /*------------------------------------------------------------------------*/
 /* Quantization matrix for the intra blocks                               */
 /*------------------------------------------------------------------------*/
 if(impeg2d_bit_stream_get_bit(ps_stream) == 1)
 {
        UWORD16 i;
 for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
 {
            ps_dec->au1_intra_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
 }

 }
 else
 {
        memcpy(ps_dec->au1_intra_quant_matrix,gau1_impeg2_intra_quant_matrix_default,
                NUM_PELS_IN_BLOCK);
 }

 /*------------------------------------------------------------------------*/
 /* Quantization matrix for the inter blocks                               */
 /*------------------------------------------------------------------------*/
 if(impeg2d_bit_stream_get_bit(ps_stream) == 1)
 {
        UWORD16 i;
 for(i = 0; i < NUM_PELS_IN_BLOCK; i++)
 {
            ps_dec->au1_inter_quant_matrix[gau1_impeg2_inv_scan_zig_zag[i]] = (UWORD8)impeg2d_bit_stream_get(ps_stream,8);
 }
 }
 else
 {
        memcpy(ps_dec->au1_inter_quant_matrix,gau1_impeg2_inter_quant_matrix_default,
            NUM_PELS_IN_BLOCK);
 }
    impeg2d_next_start_code(ps_dec);

 return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;
}


status_t BnHDCP::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case HDCP_SET_OBSERVER:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<IHDCPObserver> observer =
                interface_cast<IHDCPObserver>(data.readStrongBinder());

            reply->writeInt32(setObserver(observer));
 return OK;
 }

 case HDCP_INIT_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

 const char *host = data.readCString();
 unsigned port = data.readInt32();

            reply->writeInt32(initAsync(host, port));
 return OK;
 }

 case HDCP_SHUTDOWN_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(shutdownAsync());
 return OK;
 }

 case HDCP_GET_CAPS:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(getCaps());
 return OK;
 }

         case HDCP_ENCRYPT:
         {
             size_t size = data.readInt32();
            size_t bufSize = 2 * size;
            if (bufSize > size) {
                inData = malloc(bufSize);
             }
             if (inData == NULL) {
                 reply->writeInt32(ERROR_OUT_OF_RANGE);
                 return OK;
 }

             void *outData = (uint8_t *)inData + size;

            data.read(inData, size);

             uint32_t streamCTR = data.readInt32();
             uint64_t inputCTR;
            status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData);

             reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 case HDCP_ENCRYPT_NATIVE:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
 size_t offset = data.readInt32();
 size_t size = data.readInt32();
 uint32_t streamCTR = data.readInt32();
 void *outData = malloc(size);
 uint64_t inputCTR;

 status_t err = encryptNative(graphicBuffer, offset, size,
                                         streamCTR, &inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(outData);
            outData = NULL;

 return OK;
 }

 case HDCP_DECRYPT:
 {
 size_t size = data.readInt32();
 size_t bufSize = 2 * size;

 void *inData = NULL;
 if (bufSize > size) {
                inData = malloc(bufSize);
 }

 if (inData == NULL) {
                reply->writeInt32(ERROR_OUT_OF_RANGE);
 return OK;
 }

 void *outData = (uint8_t *)inData + size;

            data.read(inData, size);

 uint32_t streamCTR = data.readInt32();
 uint64_t inputCTR = data.readInt64();
 status_t err = decrypt(inData, size, streamCTR, inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 default:
 return BBinder::onTransact(code, data, reply, flags);
 }
}

An information disclosure vulnerability in libmedia in Mediaserver could enable a local malicious application to access data outside of its permission levels. This issue is rated as High because it is a general bypass for operating system protections that isolate application data from other applications. Product: Android. Versions: 4.4.4, 5.0.2, 5.1.1, 6.0, 6.0.1, 7.0, 7.1.1. Android ID: A-33861560.


status_t BnHDCP::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case HDCP_SET_OBSERVER:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<IHDCPObserver> observer =
                interface_cast<IHDCPObserver>(data.readStrongBinder());

            reply->writeInt32(setObserver(observer));
 return OK;
 }

 case HDCP_INIT_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

 const char *host = data.readCString();
 unsigned port = data.readInt32();

            reply->writeInt32(initAsync(host, port));
 return OK;
 }

 case HDCP_SHUTDOWN_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(shutdownAsync());
 return OK;
 }

 case HDCP_GET_CAPS:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(getCaps());
 return OK;
 }

         case HDCP_ENCRYPT:
         {
             size_t size = data.readInt32();
            // watch out for overflow
            if (size <= SIZE_MAX / 2) {
                inData = malloc(2 * size);
             }
             if (inData == NULL) {
                 reply->writeInt32(ERROR_OUT_OF_RANGE);
                 return OK;
 }

             void *outData = (uint8_t *)inData + size;

            status_t err = data.read(inData, size);
            if (err != OK) {
                free(inData);
                reply->writeInt32(err);
                return OK;
            }

             uint32_t streamCTR = data.readInt32();
             uint64_t inputCTR;
            err = encrypt(inData, size, streamCTR, &inputCTR, outData);

             reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 case HDCP_ENCRYPT_NATIVE:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
 size_t offset = data.readInt32();
 size_t size = data.readInt32();
 uint32_t streamCTR = data.readInt32();
 void *outData = malloc(size);
 uint64_t inputCTR;

 status_t err = encryptNative(graphicBuffer, offset, size,
                                         streamCTR, &inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(outData);
            outData = NULL;

 return OK;
 }

 case HDCP_DECRYPT:
 {
 size_t size = data.readInt32();
 size_t bufSize = 2 * size;

 void *inData = NULL;
 if (bufSize > size) {
                inData = malloc(bufSize);
 }

 if (inData == NULL) {
                reply->writeInt32(ERROR_OUT_OF_RANGE);
 return OK;
 }

 void *outData = (uint8_t *)inData + size;

            data.read(inData, size);

 uint32_t streamCTR = data.readInt32();
 uint64_t inputCTR = data.readInt64();
 status_t err = decrypt(inData, size, streamCTR, inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 default:
 return BBinder::onTransact(code, data, reply, flags);
 }
}


WORD32 ih264d_video_decode(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op)
{
 /* ! */

 dec_struct_t * ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle);

    WORD32 i4_err_status = 0;
    UWORD8 *pu1_buf = NULL;
    WORD32 buflen;
    UWORD32 u4_max_ofst, u4_length_of_start_code = 0;

    UWORD32 bytes_consumed = 0;
    UWORD32 cur_slice_is_nonref = 0;
    UWORD32 u4_next_is_aud;
    UWORD32 u4_first_start_code_found = 0;
    WORD32 ret = 0,api_ret_value = IV_SUCCESS;
    WORD32 header_data_left = 0,frame_data_left = 0;
    UWORD8 *pu1_bitstrm_buf;
 ivd_video_decode_ip_t *ps_dec_ip;
 ivd_video_decode_op_t *ps_dec_op;

    ithread_set_name((void*)"Parse_thread");

    ps_dec_ip = (ivd_video_decode_ip_t *)pv_api_ip;
    ps_dec_op = (ivd_video_decode_op_t *)pv_api_op;

 {
        UWORD32 u4_size;
        u4_size = ps_dec_op->u4_size;
        memset(ps_dec_op, 0, sizeof(ivd_video_decode_op_t));
        ps_dec_op->u4_size = u4_size;
 }

    ps_dec->pv_dec_out = ps_dec_op;
 if(ps_dec->init_done != 1)
 {
 return IV_FAIL;
 }

 /*Data memory barries instruction,so that bitstream write by the application is complete*/
    DATA_SYNC();

 if(0 == ps_dec->u1_flushfrm)
 {
 if(ps_dec_ip->pv_stream_buffer == NULL)
 {
            ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
            ps_dec_op->u4_error_code |= IVD_DEC_FRM_BS_BUF_NULL;
 return IV_FAIL;
 }
 if(ps_dec_ip->u4_num_Bytes <= 0)
 {
            ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
            ps_dec_op->u4_error_code |= IVD_DEC_NUMBYTES_INV;
 return IV_FAIL;

 }
 }
    ps_dec->u1_pic_decode_done = 0;

    ps_dec_op->u4_num_bytes_consumed = 0;

    ps_dec->ps_out_buffer = NULL;

 if(ps_dec_ip->u4_size
 >= offsetof(ivd_video_decode_ip_t, s_out_buffer))
        ps_dec->ps_out_buffer = &ps_dec_ip->s_out_buffer;

    ps_dec->u4_fmt_conv_cur_row = 0;

    ps_dec->u4_output_present = 0;
    ps_dec->s_disp_op.u4_error_code = 1;
    ps_dec->u4_fmt_conv_num_rows = FMT_CONV_NUM_ROWS;
 if(0 == ps_dec->u4_share_disp_buf
 && ps_dec->i4_decode_header == 0)
 {
        UWORD32 i;
 if(ps_dec->ps_out_buffer->u4_num_bufs == 0)
 {
            ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
            ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUFS;
 return IV_FAIL;
 }

 for(i = 0; i < ps_dec->ps_out_buffer->u4_num_bufs; i++)
 {
 if(ps_dec->ps_out_buffer->pu1_bufs[i] == NULL)
 {
                ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
                ps_dec_op->u4_error_code |= IVD_DISP_FRM_OP_BUF_NULL;
 return IV_FAIL;
 }

 if(ps_dec->ps_out_buffer->u4_min_out_buf_size[i] == 0)
 {
                ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
                ps_dec_op->u4_error_code |=
                                IVD_DISP_FRM_ZERO_OP_BUF_SIZE;
 return IV_FAIL;
 }
 }
 }

 if(ps_dec->u4_total_frames_decoded >= NUM_FRAMES_LIMIT)
 {
        ps_dec_op->u4_error_code = ERROR_FRAME_LIMIT_OVER;
 return IV_FAIL;
 }

 /* ! */
    ps_dec->u4_ts = ps_dec_ip->u4_ts;

    ps_dec_op->u4_error_code = 0;
    ps_dec_op->e_pic_type = -1;
    ps_dec_op->u4_output_present = 0;
    ps_dec_op->u4_frame_decoded_flag = 0;

    ps_dec->i4_frametype = -1;
    ps_dec->i4_content_type = -1;
 /*
     * For field pictures, set the bottom and top picture decoded u4_flag correctly.
     */
 {
 if((TOP_FIELD_ONLY | BOT_FIELD_ONLY) == ps_dec->u1_top_bottom_decoded)
 {
            ps_dec->u1_top_bottom_decoded = 0;
 }
 }
    ps_dec->u4_slice_start_code_found = 0;

 /* In case the deocder is not in flush mode(in shared mode),
     then decoder has to pick up a buffer to write current frame.
     Check if a frame is available in such cases */

 if(ps_dec->u1_init_dec_flag == 1 && ps_dec->u4_share_disp_buf == 1
 && ps_dec->u1_flushfrm == 0)
 {
        UWORD32 i;

        WORD32 disp_avail = 0, free_id;

 /* Check if at least one buffer is available with the codec */
 /* If not then return to application with error */
 for(i = 0; i < ps_dec->u1_pic_bufs; i++)
 {
 if(0 == ps_dec->u4_disp_buf_mapping[i]
 || 1 == ps_dec->u4_disp_buf_to_be_freed[i])
 {
                disp_avail = 1;
 break;
 }

 }

 if(0 == disp_avail)
 {
 /* If something is queued for display wait for that buffer to be returned */

            ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL;
            ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
 return (IV_FAIL);
 }

 while(1)
 {
 pic_buffer_t *ps_pic_buf;
            ps_pic_buf = (pic_buffer_t *)ih264_buf_mgr_get_next_free(
 (buf_mgr_t *)ps_dec->pv_pic_buf_mgr, &free_id);

 if(ps_pic_buf == NULL)
 {
                UWORD32 i, display_queued = 0;

 /* check if any buffer was given for display which is not returned yet */
 for(i = 0; i < (MAX_DISP_BUFS_NEW); i++)
 {
 if(0 != ps_dec->u4_disp_buf_mapping[i])
 {
                        display_queued = 1;
 break;
 }
 }
 /* If some buffer is queued for display, then codec has to singal an error and wait
                 for that buffer to be returned.
                 If nothing is queued for display then codec has ownership of all display buffers
                 and it can reuse any of the existing buffers and continue decoding */

 if(1 == display_queued)
 {
 /* If something is queued for display wait for that buffer to be returned */
                    ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL;
                    ps_dec_op->u4_error_code |= (1
 << IVD_UNSUPPORTEDPARAM);
 return (IV_FAIL);
 }
 }
 else
 {
 /* If the buffer is with display, then mark it as in use and then look for a buffer again */
 if(1 == ps_dec->u4_disp_buf_mapping[free_id])
 {
                    ih264_buf_mgr_set_status(
 (buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
                                    free_id,
                                    BUF_MGR_IO);
 }
 else
 {
 /**
                     *  Found a free buffer for present call. Release it now.
                     *  Will be again obtained later.
                     */
                    ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
                                          free_id,
                                          BUF_MGR_IO);
 break;
 }
 }
 }

 }

 if(ps_dec->u1_flushfrm && ps_dec->u1_init_dec_flag)
 {

        ih264d_get_next_display_field(ps_dec, ps_dec->ps_out_buffer,
 &(ps_dec->s_disp_op));
 if(0 == ps_dec->s_disp_op.u4_error_code)
 {
            ps_dec->u4_fmt_conv_cur_row = 0;
            ps_dec->u4_fmt_conv_num_rows = ps_dec->s_disp_frame_info.u4_y_ht;
            ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
                                  ps_dec->u4_fmt_conv_cur_row,
                                  ps_dec->u4_fmt_conv_num_rows);
            ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
            ps_dec->u4_output_present = 1;

 }
        ih264d_release_display_field(ps_dec, &(ps_dec->s_disp_op));

        ps_dec_op->u4_pic_wd = (UWORD32)ps_dec->u2_disp_width;
        ps_dec_op->u4_pic_ht = (UWORD32)ps_dec->u2_disp_height;

        ps_dec_op->u4_new_seq = 0;

        ps_dec_op->u4_output_present = ps_dec->u4_output_present;
        ps_dec_op->u4_progressive_frame_flag =
                        ps_dec->s_disp_op.u4_progressive_frame_flag;
        ps_dec_op->e_output_format =
                        ps_dec->s_disp_op.e_output_format;
        ps_dec_op->s_disp_frm_buf = ps_dec->s_disp_op.s_disp_frm_buf;
        ps_dec_op->e4_fld_type = ps_dec->s_disp_op.e4_fld_type;
        ps_dec_op->u4_ts = ps_dec->s_disp_op.u4_ts;
        ps_dec_op->u4_disp_buf_id = ps_dec->s_disp_op.u4_disp_buf_id;

 /*In the case of flush ,since no frame is decoded set pic type as invalid*/
        ps_dec_op->u4_is_ref_flag = -1;
        ps_dec_op->e_pic_type = IV_NA_FRAME;
        ps_dec_op->u4_frame_decoded_flag = 0;

 if(0 == ps_dec->s_disp_op.u4_error_code)
 {
 return (IV_SUCCESS);
 }
 else
 return (IV_FAIL);

 }
 if(ps_dec->u1_res_changed == 1)
 {
 /*if resolution has changed and all buffers have been flushed, reset decoder*/
        ih264d_init_decoder(ps_dec);
 }

    ps_dec->u4_prev_nal_skipped = 0;

    ps_dec->u2_cur_mb_addr = 0;
    ps_dec->u2_total_mbs_coded = 0;
    ps_dec->u2_cur_slice_num = 0;
    ps_dec->cur_dec_mb_num = 0;
    ps_dec->cur_recon_mb_num = 0;
    ps_dec->u4_first_slice_in_pic = 2;
    ps_dec->u1_first_pb_nal_in_pic = 1;
    ps_dec->u1_slice_header_done = 0;
    ps_dec->u1_dangling_field = 0;

    ps_dec->u4_dec_thread_created = 0;
    ps_dec->u4_bs_deblk_thread_created = 0;
    ps_dec->u4_cur_bs_mb_num = 0;
    ps_dec->u4_start_recon_deblk  = 0;

    DEBUG_THREADS_PRINTF(" Starting process call\n");

    ps_dec->u4_pic_buf_got = 0;

 do
 {
        WORD32 buf_size;

        pu1_buf = (UWORD8*)ps_dec_ip->pv_stream_buffer
 + ps_dec_op->u4_num_bytes_consumed;

        u4_max_ofst = ps_dec_ip->u4_num_Bytes
 - ps_dec_op->u4_num_bytes_consumed;

 /* If dynamic bitstream buffer is not allocated and
         * header decode is done, then allocate dynamic bitstream buffer
         */
 if((NULL == ps_dec->pu1_bits_buf_dynamic) &&
 (ps_dec->i4_header_decoded & 1))
 {
            WORD32 size;

 void *pv_buf;
 void *pv_mem_ctxt = ps_dec->pv_mem_ctxt;
            size = MAX(256000, ps_dec->u2_pic_wd * ps_dec->u2_pic_ht * 3 / 2);
            pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
            RETURN_IF((NULL == pv_buf), IV_FAIL);
            ps_dec->pu1_bits_buf_dynamic = pv_buf;
            ps_dec->u4_dynamic_bits_buf_size = size;
 }

 if(ps_dec->pu1_bits_buf_dynamic)
 {
            pu1_bitstrm_buf = ps_dec->pu1_bits_buf_dynamic;
            buf_size = ps_dec->u4_dynamic_bits_buf_size;
 }
 else
 {
            pu1_bitstrm_buf = ps_dec->pu1_bits_buf_static;
            buf_size = ps_dec->u4_static_bits_buf_size;
 }

        u4_next_is_aud = 0;

        buflen = ih264d_find_start_code(pu1_buf, 0, u4_max_ofst,
 &u4_length_of_start_code,
 &u4_next_is_aud);

         if(buflen == -1)
             buflen = 0;
         /* Ignore bytes beyond the allocated size of intermediate buffer */
        buflen = MIN(buflen, buf_size);

         bytes_consumed = buflen + u4_length_of_start_code;
         ps_dec_op->u4_num_bytes_consumed += bytes_consumed;

 {
            UWORD8 u1_firstbyte, u1_nal_ref_idc;

 if(ps_dec->i4_app_skip_mode == IVD_SKIP_B)
 {
                u1_firstbyte = *(pu1_buf + u4_length_of_start_code);
                u1_nal_ref_idc = (UWORD8)(NAL_REF_IDC(u1_firstbyte));
 if(u1_nal_ref_idc == 0)
 {
 /*skip non reference frames*/
                    cur_slice_is_nonref = 1;
 continue;
 }
 else
 {
 if(1 == cur_slice_is_nonref)
 {
 /*We have encountered a referenced frame,return to app*/
                        ps_dec_op->u4_num_bytes_consumed -=
                                        bytes_consumed;
                        ps_dec_op->e_pic_type = IV_B_FRAME;
                        ps_dec_op->u4_error_code =
                                        IVD_DEC_FRM_SKIPPED;
                        ps_dec_op->u4_error_code |= (1
 << IVD_UNSUPPORTEDPARAM);
                        ps_dec_op->u4_frame_decoded_flag = 0;
                        ps_dec_op->u4_size =
 sizeof(ivd_video_decode_op_t);
 /*signal the decode thread*/
                        ih264d_signal_decode_thread(ps_dec);
 /* close deblock thread if it is not closed yet*/
 if(ps_dec->u4_num_cores == 3)
 {
                            ih264d_signal_bs_deblk_thread(ps_dec);
 }

 return (IV_FAIL);
 }
 }

 }

 }

 if(buflen)
 {
            memcpy(pu1_bitstrm_buf, pu1_buf + u4_length_of_start_code,
                   buflen);
 /* Decoder may read extra 8 bytes near end of the frame */
 if((buflen + 8) < buf_size)
 {
                memset(pu1_bitstrm_buf + buflen, 0, 8);
 }
            u4_first_start_code_found = 1;

 }
 else
 {
 /*start code not found*/

 if(u4_first_start_code_found == 0)
 {
 /*no start codes found in current process call*/

                ps_dec->i4_error_code = ERROR_START_CODE_NOT_FOUND;
                ps_dec_op->u4_error_code |= 1 << IVD_INSUFFICIENTDATA;

 if(ps_dec->u4_pic_buf_got == 0)
 {

                    ih264d_fill_output_struct_from_context(ps_dec,
                                                           ps_dec_op);

                    ps_dec_op->u4_error_code = ps_dec->i4_error_code;
                    ps_dec_op->u4_frame_decoded_flag = 0;

 return (IV_FAIL);
 }
 else
 {
                    ps_dec->u1_pic_decode_done = 1;
 continue;
 }
 }
 else
 {
 /* a start code has already been found earlier in the same process call*/
                frame_data_left = 0;
                header_data_left = 0;
 continue;
 }

 }

        ps_dec->u4_return_to_app = 0;
        ret = ih264d_parse_nal_unit(dec_hdl, ps_dec_op,
                              pu1_bitstrm_buf, buflen);
 if(ret != OK)
 {
            UWORD32 error =  ih264d_map_error(ret);
            ps_dec_op->u4_error_code = error | ret;
            api_ret_value = IV_FAIL;

 if((ret == IVD_RES_CHANGED)
 || (ret == IVD_MEM_ALLOC_FAILED)
 || (ret == ERROR_UNAVAIL_PICBUF_T)
 || (ret == ERROR_UNAVAIL_MVBUF_T)
 || (ret == ERROR_INV_SPS_PPS_T))
 {
                ps_dec->u4_slice_start_code_found = 0;
 break;
 }

 if((ret == ERROR_INCOMPLETE_FRAME) || (ret == ERROR_DANGLING_FIELD_IN_PIC))
 {
                ps_dec_op->u4_num_bytes_consumed -= bytes_consumed;
                api_ret_value = IV_FAIL;
 break;
 }

 if(ret == ERROR_IN_LAST_SLICE_OF_PIC)
 {
                api_ret_value = IV_FAIL;
 break;
 }

 }

 if(ps_dec->u4_return_to_app)
 {
 /*We have encountered a referenced frame,return to app*/
            ps_dec_op->u4_num_bytes_consumed -= bytes_consumed;
            ps_dec_op->u4_error_code = IVD_DEC_FRM_SKIPPED;
            ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
            ps_dec_op->u4_frame_decoded_flag = 0;
            ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
 /*signal the decode thread*/
            ih264d_signal_decode_thread(ps_dec);
 /* close deblock thread if it is not closed yet*/
 if(ps_dec->u4_num_cores == 3)
 {
                ih264d_signal_bs_deblk_thread(ps_dec);
 }
 return (IV_FAIL);

 }

        header_data_left = ((ps_dec->i4_decode_header == 1)
 && (ps_dec->i4_header_decoded != 3)
 && (ps_dec_op->u4_num_bytes_consumed
 < ps_dec_ip->u4_num_Bytes));
        frame_data_left = (((ps_dec->i4_decode_header == 0)
 && ((ps_dec->u1_pic_decode_done == 0)
 || (u4_next_is_aud == 1)))
 && (ps_dec_op->u4_num_bytes_consumed
 < ps_dec_ip->u4_num_Bytes));
 }
 while(( header_data_left == 1)||(frame_data_left == 1));

 if((ps_dec->u4_slice_start_code_found == 1)
 && (ret != IVD_MEM_ALLOC_FAILED)
 && ps_dec->u2_total_mbs_coded < ps_dec->u2_frm_ht_in_mbs * ps_dec->u2_frm_wd_in_mbs)
 {
        WORD32 num_mb_skipped;
        WORD32 prev_slice_err;
 pocstruct_t temp_poc;
        WORD32 ret1;
        WORD32 ht_in_mbs;
        ht_in_mbs = ps_dec->u2_pic_ht >> (4 + ps_dec->ps_cur_slice->u1_field_pic_flag);
        num_mb_skipped = (ht_in_mbs * ps_dec->u2_frm_wd_in_mbs)
 - ps_dec->u2_total_mbs_coded;

 if(ps_dec->u4_first_slice_in_pic && (ps_dec->u4_pic_buf_got == 0))
            prev_slice_err = 1;
 else
            prev_slice_err = 2;

 if(ps_dec->u4_first_slice_in_pic && (ps_dec->u2_total_mbs_coded == 0))
            prev_slice_err = 1;

        ret1 = ih264d_mark_err_slice_skip(ps_dec, num_mb_skipped, ps_dec->u1_nal_unit_type == IDR_SLICE_NAL, ps_dec->ps_cur_slice->u2_frame_num,
 &temp_poc, prev_slice_err);

 if((ret1 == ERROR_UNAVAIL_PICBUF_T) || (ret1 == ERROR_UNAVAIL_MVBUF_T) ||
 (ret1 == ERROR_INV_SPS_PPS_T))
 {
            ret = ret1;
 }
 }

 if((ret == IVD_RES_CHANGED)
 || (ret == IVD_MEM_ALLOC_FAILED)
 || (ret == ERROR_UNAVAIL_PICBUF_T)
 || (ret == ERROR_UNAVAIL_MVBUF_T)
 || (ret == ERROR_INV_SPS_PPS_T))
 {

 /* signal the decode thread */
        ih264d_signal_decode_thread(ps_dec);
 /* close deblock thread if it is not closed yet */
 if(ps_dec->u4_num_cores == 3)
 {
            ih264d_signal_bs_deblk_thread(ps_dec);
 }
 /* dont consume bitstream for change in resolution case */
 if(ret == IVD_RES_CHANGED)
 {
            ps_dec_op->u4_num_bytes_consumed -= bytes_consumed;
 }
 return IV_FAIL;
 }

 if(ps_dec->u1_separate_parse)
 {
 /* If Format conversion is not complete,
         complete it here */
 if(ps_dec->u4_num_cores == 2)
 {

 /*do deblocking of all mbs*/
 if((ps_dec->u4_nmb_deblk == 0) &&(ps_dec->u4_start_recon_deblk == 1) && (ps_dec->ps_cur_sps->u1_mb_aff_flag == 0))
 {
                UWORD32 u4_num_mbs,u4_max_addr;
 tfr_ctxt_t s_tfr_ctxt;
 tfr_ctxt_t *ps_tfr_cxt = &s_tfr_ctxt;
 pad_mgr_t *ps_pad_mgr = &ps_dec->s_pad_mgr;

 /*BS is done for all mbs while parsing*/
                u4_max_addr = (ps_dec->u2_frm_wd_in_mbs * ps_dec->u2_frm_ht_in_mbs) - 1;
                ps_dec->u4_cur_bs_mb_num = u4_max_addr + 1;

                ih264d_init_deblk_tfr_ctxt(ps_dec, ps_pad_mgr, ps_tfr_cxt,
                                           ps_dec->u2_frm_wd_in_mbs, 0);

                u4_num_mbs = u4_max_addr
 - ps_dec->u4_cur_deblk_mb_num + 1;

                DEBUG_PERF_PRINTF("mbs left for deblocking= %d \n",u4_num_mbs);

 if(u4_num_mbs != 0)
                    ih264d_check_mb_map_deblk(ps_dec, u4_num_mbs,
                                                   ps_tfr_cxt,1);

                ps_dec->u4_start_recon_deblk  = 0;

 }

 }

 /*signal the decode thread*/
        ih264d_signal_decode_thread(ps_dec);
 /* close deblock thread if it is not closed yet*/
 if(ps_dec->u4_num_cores == 3)
 {
            ih264d_signal_bs_deblk_thread(ps_dec);
 }
 }

    DATA_SYNC();

 if((ps_dec_op->u4_error_code & 0xff)
 != ERROR_DYNAMIC_RESOLUTION_NOT_SUPPORTED)
 {
        ps_dec_op->u4_pic_wd = (UWORD32)ps_dec->u2_disp_width;
        ps_dec_op->u4_pic_ht = (UWORD32)ps_dec->u2_disp_height;
 }

 if(ps_dec->i4_header_decoded != 3)
 {
        ps_dec_op->u4_error_code |= (1 << IVD_INSUFFICIENTDATA);

 }

 if(ps_dec->i4_decode_header == 1 && ps_dec->i4_header_decoded != 3)
 {
        ps_dec_op->u4_error_code |= (1 << IVD_INSUFFICIENTDATA);

 }
 if(ps_dec->u4_prev_nal_skipped)
 {
 /*We have encountered a referenced frame,return to app*/
        ps_dec_op->u4_error_code = IVD_DEC_FRM_SKIPPED;
        ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
        ps_dec_op->u4_frame_decoded_flag = 0;
        ps_dec_op->u4_size = sizeof(ivd_video_decode_op_t);
 /* close deblock thread if it is not closed yet*/
 if(ps_dec->u4_num_cores == 3)
 {
            ih264d_signal_bs_deblk_thread(ps_dec);
 }
 return (IV_FAIL);

 }

 if((ps_dec->u4_slice_start_code_found == 1)
 && (ERROR_DANGLING_FIELD_IN_PIC != i4_err_status))
 {
 /*
         * For field pictures, set the bottom and top picture decoded u4_flag correctly.
         */

 if(ps_dec->ps_cur_slice->u1_field_pic_flag)
 {
 if(1 == ps_dec->ps_cur_slice->u1_bottom_field_flag)
 {
                ps_dec->u1_top_bottom_decoded |= BOT_FIELD_ONLY;
 }
 else
 {
                ps_dec->u1_top_bottom_decoded |= TOP_FIELD_ONLY;
 }
 }

 /* if new frame in not found (if we are still getting slices from previous frame)
         * ih264d_deblock_display is not called. Such frames will not be added to reference /display
         */
 if (((ps_dec->ps_dec_err_status->u1_err_flag & REJECT_CUR_PIC) == 0)
 && (ps_dec->u4_pic_buf_got == 1))
 {
 /* Calling Function to deblock Picture and Display */
            ret = ih264d_deblock_display(ps_dec);
 if(ret != 0)
 {
 return IV_FAIL;
 }
 }

 /*set to complete ,as we dont support partial frame decode*/
 if(ps_dec->i4_header_decoded == 3)
 {
            ps_dec->u2_total_mbs_coded = ps_dec->ps_cur_sps->u2_max_mb_addr + 1;
 }

 /*Update the i4_frametype at the end of picture*/
 if(ps_dec->ps_cur_slice->u1_nal_unit_type == IDR_SLICE_NAL)
 {
            ps_dec->i4_frametype = IV_IDR_FRAME;
 }
 else if(ps_dec->i4_pic_type == B_SLICE)
 {
            ps_dec->i4_frametype = IV_B_FRAME;
 }
 else if(ps_dec->i4_pic_type == P_SLICE)
 {
            ps_dec->i4_frametype = IV_P_FRAME;
 }
 else if(ps_dec->i4_pic_type == I_SLICE)
 {
            ps_dec->i4_frametype = IV_I_FRAME;
 }
 else
 {
            H264_DEC_DEBUG_PRINT("Shouldn't come here\n");
 }

        ps_dec->i4_content_type = ps_dec->ps_cur_slice->u1_field_pic_flag;

        ps_dec->u4_total_frames_decoded = ps_dec->u4_total_frames_decoded + 2;
        ps_dec->u4_total_frames_decoded = ps_dec->u4_total_frames_decoded
 - ps_dec->ps_cur_slice->u1_field_pic_flag;

 }

 /* close deblock thread if it is not closed yet*/
 if(ps_dec->u4_num_cores == 3)
 {
        ih264d_signal_bs_deblk_thread(ps_dec);
 }

 {
 /* In case the decoder is configured to run in low delay mode,
         * then get display buffer and then format convert.
         * Note in this mode, format conversion does not run paralelly in a thread and adds to the codec cycles
         */

 if((IVD_DECODE_FRAME_OUT == ps_dec->e_frm_out_mode)
 && ps_dec->u1_init_dec_flag)
 {

            ih264d_get_next_display_field(ps_dec, ps_dec->ps_out_buffer,
 &(ps_dec->s_disp_op));
 if(0 == ps_dec->s_disp_op.u4_error_code)
 {
                ps_dec->u4_fmt_conv_cur_row = 0;
                ps_dec->u4_output_present = 1;
 }
 }

        ih264d_fill_output_struct_from_context(ps_dec, ps_dec_op);

 /* If Format conversion is not complete,
         complete it here */
 if(ps_dec->u4_output_present &&
 (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
 {
            ps_dec->u4_fmt_conv_num_rows = ps_dec->s_disp_frame_info.u4_y_ht
 - ps_dec->u4_fmt_conv_cur_row;
            ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
                                  ps_dec->u4_fmt_conv_cur_row,
                                  ps_dec->u4_fmt_conv_num_rows);
            ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
 }

        ih264d_release_display_field(ps_dec, &(ps_dec->s_disp_op));
 }

 if(ps_dec->i4_decode_header == 1 && (ps_dec->i4_header_decoded & 1) == 1)
 {
        ps_dec_op->u4_progressive_frame_flag = 1;
 if((NULL != ps_dec->ps_cur_sps) && (1 == (ps_dec->ps_cur_sps->u1_is_valid)))
 {
 if((0 == ps_dec->ps_sps->u1_frame_mbs_only_flag)
 && (0 == ps_dec->ps_sps->u1_mb_aff_flag))
                ps_dec_op->u4_progressive_frame_flag = 0;

 }
 }

 /*Data memory barrier instruction,so that yuv write by the library is complete*/
    DATA_SYNC();

    H264_DEC_DEBUG_PRINT("The num bytes consumed: %d\n",
                         ps_dec_op->u4_num_bytes_consumed);
 return api_ret_value;
}

A remote code execution vulnerability in libavc in Mediaserver could enable an attacker using a specially crafted file to cause memory corruption during media file and data processing. This issue is rated as Critical due to the possibility of remote code execution within the context of the Mediaserver process. Product: Android. Versions: 6.0, 6.0.1, 7.0, 7.1.1. Android ID: A-33934721.