Commit message: None
CVE: CVE-2016-0836
CWE: CWE-119
Vulnerability description: Stack-based buffer overflow in decoder/impeg2d_vld.c in mediaserver in Android 6.x before 2016-04-01 allows remote attackers to execute arbitrary code or cause a denial of service (memory corruption) via a crafted media file, aka internal bug 25812590.

Project: Android

UWORD8 impeg2d_inv_quant_mpeg2(WORD16 *pi2_blk,
                              UWORD8 *pu1_weighting_matrix,
                              UWORD8 u1_quant_scale,
                              WORD32 u4_intra_flag,
                              WORD32 i4_num_coeffs,
                              WORD16 *pi2_coeffs,
                              UWORD8 *pu1_pos,
 const UWORD8 *pu1_scan,
                              UWORD16 *pu2_def_dc_pred,
                              UWORD16 u2_intra_dc_precision)
{

    WORD32  i4_pos;
 /* Used for Mismatch control */
    UWORD32 sum;

    WORD32  i4_iter;

    sum = 0;

 /* Inverse Quantize the predicted DC value for intra MB*/
 if(u4_intra_flag == 1)
 {
 /**************************************************************************/
 /* Decode the DC coefficient in case of Intra block and also update       */
 /* DC predictor value of the corresponding color component                */
 /**************************************************************************/
 {
            pi2_coeffs[0] += *pu2_def_dc_pred;
 *pu2_def_dc_pred      = pi2_coeffs[0];
            pi2_coeffs[0] <<= (3 - u2_intra_dc_precision);
            pi2_coeffs[0] = CLIP_S12(pi2_coeffs[0]);
 }

        pi2_blk[pu1_scan[0]] = pi2_coeffs[0];
        sum = pi2_blk[0];
 }

 /************************************************************************/
 /* Inverse quantization of other DCT coefficients                       */
 /************************************************************************/
 for(i4_iter = u4_intra_flag; i4_iter < i4_num_coeffs; i4_iter++)
 {
        WORD16 sign;
        WORD32 temp;
 /* Position is the inverse scan of the index stored */
        i4_pos      = pu1_pos[i4_iter];
        pi2_blk[i4_pos] = pi2_coeffs[i4_iter];

        sign = SIGN(pi2_blk[i4_pos]);
        temp = ABS(pi2_blk[i4_pos] << 1);
        temp = temp + (1 * !u4_intra_flag);
        temp = temp * pu1_weighting_matrix[i4_pos] * u1_quant_scale;

        temp = temp >> 5;

        temp = temp * sign;

        temp = CLIP_S12(temp);

        pi2_blk[i4_pos] = temp;

        sum += temp;
 }
 return (sum ^ 1);
} /* End of inv_quant() */

Project: Android

IMPEG2D_ERROR_CODES_T impeg2d_vld_inv_quant_mpeg1(
 void *pv_dec, /* Decoder State */
                             WORD16       *pi2_out_addr, /*!< Address where decoded symbols will be stored */
 const UWORD8 *pu1_scan, /*!< Scan table to be used */
                             UWORD16      u2_intra_flag, /*!< Intra Macroblock or not */
                             UWORD16      u2_colr_comp, /*!< 0 - Luma,1 - U comp, 2 - V comp */
                             UWORD16      u2_d_picture        /*!< D Picture or not */
 )
{
    UWORD8  *pu1_weighting_matrix;
 dec_state_t *ps_dec    = (dec_state_t *) pv_dec;
    IMPEG2D_ERROR_CODES_T e_error   = (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE;

    WORD16  pi2_coeffs[NUM_COEFFS];
    UWORD8  pu1_pos[NUM_COEFFS];
    WORD32  i4_num_coeffs;

 /* Perform VLD on the stream to get the coefficients and their positions */
    e_error = impeg2d_vld_decode(ps_dec, pi2_coeffs, pu1_scan, pu1_pos, u2_intra_flag,
                                 u2_colr_comp, u2_d_picture, ps_dec->u2_intra_vlc_format,
                                 ps_dec->u2_is_mpeg2, &i4_num_coeffs);
 if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
 {
 return e_error;
 }

 /* For YUV420 format,Select the weighting matrix according to Table 7.5 */
    pu1_weighting_matrix = (u2_intra_flag == 1) ? ps_dec->au1_intra_quant_matrix:
                    ps_dec->au1_inter_quant_matrix;

    IMPEG2D_IQNT_INP_STATISTICS(pi2_out_addr, ps_dec->u4_non_zero_cols, ps_dec->u4_non_zero_rows);
 /* Inverse Quantize the Output of VLD */
    PROFILE_DISABLE_INVQUANT_IF0

 {
 /* Clear output matrix */
        PROFILE_DISABLE_MEMSET_RESBUF_IF0
 if (1 != (ps_dec->u4_non_zero_cols | ps_dec->u4_non_zero_rows))
 {
            ps_dec->pf_memset_16bit_8x8_linear_block (pi2_out_addr);
 }

        impeg2d_inv_quant_mpeg1(pi2_out_addr, pu1_weighting_matrix,
                                  ps_dec->u1_quant_scale, u2_intra_flag,
                                  i4_num_coeffs, pi2_coeffs, pu1_pos,
                                  pu1_scan, &ps_dec->u2_def_dc_pred[u2_colr_comp],
                                  ps_dec->u2_intra_dc_precision);

 if (0 != pi2_out_addr[0])
 {
 /* The first coeff might've become non-zero due to intra_dc_decision
             * value. So, check here after inverse quantization.
             */
            ps_dec->u4_non_zero_cols  |= 0x1;
            ps_dec->u4_non_zero_rows  |= 0x1;
 }
 }

 return e_error;
}