shithub: openh264

Download patch

ref: 0fcd066cde0e384ca71ef8677f88c7fcd8fc41dd
parent: 413b301e9c048413f59a127414d3453cef26e83b
parent: 61b64190ddd6c7eada8fb3e3933009411ee98a1d
author: huili2 <[email protected]>
date: Wed Feb 19 03:57:50 EST 2014

Merge pull request #298 from licaiguo/decoder-syntax-element-step1

add decoder syntax checks

--- a/codec/decoder/core/inc/dec_golomb.h
+++ b/codec/decoder/core/inc/dec_golomb.h
@@ -211,6 +211,95 @@
 
 return 0;
 }
+//define macros to check syntax elements
+#define WELS_CHECK_SE_BOTH_ERROR(val, lower_bound, upper_bound, syntax_name, ret_code) do {\
+if ((val < lower_bound) || (val > upper_bound)) {\
+  WelsLog(pCtx, WELS_LOG_ERROR, "invalid syntax " syntax_name " %d\n", val);\
+  return ret_code;\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_LOWER_ERROR(val, lower_bound, syntax_name, ret_code) do {\
+if (val < lower_bound) {\
+  WelsLog(pCtx, WELS_LOG_ERROR, "invalid syntax " syntax_name " %d\n", val);\
+  return ret_code;\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_UPPER_ERROR(val, upper_bound, syntax_name, ret_code) do {\
+if (val > upper_bound) {\
+  WelsLog(pCtx, WELS_LOG_ERROR, "invalid syntax " syntax_name " %d\n", val);\
+  return ret_code;\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_BOTH_ERROR_NOLOG(val, lower_bound, upper_bound, syntax_name, ret_code) do {\
+if ((val < lower_bound) || (val > upper_bound)) {\
+  return ret_code;\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_LOWER_ERROR_NOLOG(val, lower_bound, syntax_name, ret_code) do {\
+if (val < lower_bound) {\
+  return ret_code;\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_UPPER_ERROR_NOLOG(val, upper_bound, syntax_name, ret_code) do {\
+if (val > upper_bound) {\
+  return ret_code;\
+}\
+}while(0)
+
+
+#define WELS_CHECK_SE_BOTH_WARNING(val, lower_bound, upper_bound, syntax_name) do {\
+if ((val < lower_bound) || (val > upper_bound)) {\
+  WelsLog(pCtx, WELS_LOG_WARNING, "invalid syntax " syntax_name " %d\n", val);\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_LOWER_WARNING(val, lower_bound, syntax_name) do {\
+if (val < lower_bound) {\
+  WelsLog(pCtx, WELS_LOG_WARNING, "invalid syntax " syntax_name " %d\n", val);\
+}\
+}while(0)
+
+#define WELS_CHECK_SE_UPPER_WARNING(val, upper_bound, syntax_name) do {\
+if (val > upper_bound) {\
+  WelsLog(pCtx, WELS_LOG_WARNING, "invalid syntax " syntax_name " %d\n", val);\
+}\
+}while(0)
+// below define syntax element offset
+// for bit_depth_luma_minus8 and bit_depth_chroma_minus8
+#define BIT_DEPTH_LUMA_OFFSET 8
+#define BIT_DEPTH_CHROMA_OFFSET 8
+// for log2_max_frame_num_minus4
+#define LOG2_MAX_FRAME_NUM_OFFSET 4
+// for log2_max_pic_order_cnt_lsb_minus4
+#define LOG2_MAX_PIC_ORDER_CNT_LSB_OFFSET 4
+// for pic_width_in_mbs_minus1
+#define PIC_WIDTH_IN_MBS_OFFSET 1
+// for pic_height_in_map_units_minus1
+#define PIC_HEIGHT_IN_MAP_UNITS_OFFSET 1
+// for bit_depth_aux_minus8
+#define BIT_DEPTH_AUX_OFFSET 8
+// for num_slice_groups_minus1
+#define NUM_SLICE_GROUPS_OFFSET 1
+// for run_length_minus1
+#define RUN_LENGTH_OFFSET 1
+// for slice_group_change_rate_minus1
+#define SLICE_GROUP_CHANGE_RATE_OFFSET 1
+// for pic_size_in_map_units_minus1
+#define PIC_SIZE_IN_MAP_UNITS_OFFSET 1
+// for num_ref_idx_l0_default_active_minus1 and num_ref_idx_l1_default_active_minus1
+#define NUM_REF_IDX_L0_DEFAULT_ACTIVE_OFFSET 1
+#define NUM_REF_IDX_L1_DEFAULT_ACTIVE_OFFSET 1
+// for pic_init_qp_minus26 and pic_init_qs_minus26
+#define PIC_INIT_QP_OFFSET 26
+#define PIC_INIT_QS_OFFSET 26
+// for num_ref_idx_l0_active_minus1 and num_ref_idx_l1_active_minus1
+#define NUM_REF_IDX_L0_ACTIVE_OFFSET 1
+#define NUM_REF_IDX_L1_ACTIVE_OFFSET 1
 
 } // namespace WelsDec
 
--- a/codec/decoder/core/inc/error_code.h
+++ b/codec/decoder/core/inc/error_code.h
@@ -99,14 +99,28 @@
 ERR_INFO_INVALID_PROFILE_IDC,
 ERR_INFO_UNMATCHED_LEVEL_IDC,
 ERR_INFO_INVALID_POC_TYPE,
+ERR_INFO_INVALID_MB_SIZE_INFO,
 ERR_INFO_REF_COUNT_OVERFLOW,
 ERR_INFO_CROPPING_NO_SUPPORTED,
 ERR_INFO_INVALID_SLICEGROUP,
 ERR_INFO_INVALID_SLICEGROUP_MAP_TYPE,
 ERR_INFO_INVALID_FRAME_NUM,
+ERR_INFO_INVALID_IDR_PIC_ID,
+ERR_INFO_INVALID_REDUNDANT_PIC_CNT,
+ERR_INFO_INVALID_MAX_NUM_REF_FRAMES,
+ERR_INFO_INVALID_FIRST_MB_IN_SLICE,
+ERR_INFO_INVALID_NUM_REF_IDX_L0_ACTIVE_MINUS1,
+ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2,
+ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2,
 ERR_INFO_FMO_INIT_FAIL,
 ERR_INFO_SLICE_TYPE_OVERFLOW,
 ERR_INFO_INVALID_QP,
+ERR_INFO_INVALID_PIC_INIT_QS,
+ERR_INFO_INVALID_CHROMA_QP_INDEX_OFFSET,
+ERR_INFO_INVALID_PIC_INIT_QP,
+ERR_INFO_INVALID_LOG2_MAX_FRAME_NUM_MINUS4,
+ERR_INFO_INVALID_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4,
+ERR_INFO_INVALID_NUM_REF_FRAME_IN_PIC_ORDER_CNT_CYCLE,
 ERR_INFO_INVALID_DBLOCKING_IDC,
 ERR_INFO_INVALID_MB_TYPE,
 ERR_INFO_INVALID_SUB_MB_TYPE,
--- a/codec/decoder/core/src/au_parser.cpp
+++ b/codec/decoder/core/src/au_parser.cpp
@@ -600,7 +600,18 @@
   }
 }
 
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MIN -32768
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MAX 32767
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MIN -32768
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MAX 32767
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MIN -32768
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MAX 32767
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MIN -32768
+#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MAX 32767
 
+
+
+
 int32_t DecodeSpsSvcExt (PWelsDecoderContext pCtx, PSubsetSps pSpsExt, PBitStringAux pBs) {
   PSpsSvcExt  pExt			= NULL;
   uint8_t uiChromaArrayType	= 1;
@@ -633,9 +644,17 @@
     pExt->uiSeqRefLayerChromaPhaseYPlus1		= BsGetBits (pBs, 2);
 
     kpPos->iLeftOffset	= BsGetSe (pBs);
+    WELS_CHECK_SE_BOTH_WARNING (kpPos->iLeftOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MIN,
+                                SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MAX, "seq_scaled_ref_layer_left_offset");
     kpPos->iTopOffset	= BsGetSe (pBs);
+    WELS_CHECK_SE_BOTH_WARNING (kpPos->iTopOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MIN,
+                                SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MAX, "seq_scaled_ref_layer_top_offset");
     kpPos->iRightOffset	= BsGetSe (pBs);
+    WELS_CHECK_SE_BOTH_WARNING (kpPos->iRightOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MIN,
+                                SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MAX, "seq_scaled_ref_layer_right_offset");
     kpPos->iBottomOffset = BsGetSe (pBs);
+    WELS_CHECK_SE_BOTH_WARNING (kpPos->iBottomOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MIN,
+                                SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MAX, "seq_scaled_ref_layer_bottom_offset");
   }
 
   pExt->bSeqTCoeffLevelPredFlag	= !!BsGetOneBit (pBs);
@@ -675,7 +694,7 @@
   case 10:
     return &g_kSLevelLimits[0];
   case 11:
-    if(bConstraint3)
+    if (bConstraint3)
       return &g_kSLevelLimits[1];
     else
       return &g_kSLevelLimits[2];
@@ -712,6 +731,16 @@
   }
   return NULL;
 }
+
+#define  SPS_LOG2_MAX_FRAME_NUM_MINUS4_MAX 12
+#define  SPS_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4_MAX 12
+#define  SPS_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE_MAX 255
+#define  SPS_MAX_NUM_REF_FRAMES_MAX 16
+#define  PPS_PIC_INIT_QP_QS_MIN 0
+#define  PPS_PIC_INIT_QP_QS_MAX 51
+#define  PPS_CHROMA_QP_INDEX_OFFSET_MIN -12
+#define  PPS_CHROMA_QP_INDEX_OFFSET_MAX 12
+
 /*!
  *************************************************************************************
  * \brief	to parse Sequence Parameter Set (SPS)
@@ -728,7 +757,6 @@
  *************************************************************************************
  */
 
-
 int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight) {
   PBitStringAux pBs		= pBsAux;
   PSps pSps				= NULL;
@@ -737,10 +765,10 @@
   ProfileIdc	uiProfileIdc;
   uint8_t	uiLevelIdc;
   int32_t iSpsId;
+  uint32_t uiTmp;
   bool bConstraintSetFlags[6] = { false };
   const bool kbUseSubsetFlag   = IS_SUBSET_SPS_NAL (pNalHead->eNalUnitType);
 
-
   if (kbUseSubsetFlag) {	// SubsetSps
     pCtx->bSubspsExistAheadFlag	= true;
   } else {	// Sps
@@ -799,12 +827,11 @@
     pCtx->bSpsAvailFlags[iSpsId] = true; // added for EC, 10/28/2009
 #endif //MOSAIC_AVOID_BASED_ON_SPS_PPS_ID
   }
-  const SLevelLimits *pSLevelLimits = GetLevelLimits(uiLevelIdc, bConstraintSetFlags[3]);
+  const SLevelLimits* pSLevelLimits = GetLevelLimits (uiLevelIdc, bConstraintSetFlags[3]);
   if (NULL == pSLevelLimits) {
-     WelsLog (pCtx, WELS_LOG_WARNING, "ParseSps(): level_idx (%d).\n", uiLevelIdc);
-     return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
-  }
-  else pSps->pSLevelLimits = pSLevelLimits;
+    WelsLog (pCtx, WELS_LOG_WARNING, "ParseSps(): level_idx (%d).\n", uiLevelIdc);
+    return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
+  } else pSps->pSLevelLimits = pSLevelLimits;
   // syntax elements in default
   pSps->uiChromaFormatIdc	= 1;
   pSps->uiBitDepthLuma		=
@@ -845,12 +872,18 @@
       return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
     }
   }
-
-  pSps->uiLog2MaxFrameNum	= 4 + BsGetUe (pBs);	// log2_max_frame_num_minus4
+  uiTmp = BsGetUe (pBs);
+  WELS_CHECK_SE_UPPER_ERROR (uiTmp, SPS_LOG2_MAX_FRAME_NUM_MINUS4_MAX, "log2_max_frame_num_minus4",
+                             GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_LOG2_MAX_FRAME_NUM_MINUS4));
+  pSps->uiLog2MaxFrameNum	= LOG2_MAX_FRAME_NUM_OFFSET + uiTmp;	// log2_max_frame_num_minus4
   pSps->uiPocType			= BsGetUe (pBs);		// pic_order_cnt_type
 
   if (0 == pSps->uiPocType) {
-    pSps->iLog2MaxPocLsb	= 4 + BsGetUe (pBs);	// log2_max_pic_order_cnt_lsb_minus4
+    uiTmp = BsGetUe (pBs);
+    // log2_max_pic_order_cnt_lsb_minus4 should be in range 0 to 12, inclusive. (sec. 7.4.3)
+    WELS_CHECK_SE_UPPER_ERROR (uiTmp, SPS_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4_MAX, "log2_max_pic_order_cnt_lsb_minus4",
+                               GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4));
+    pSps->iLog2MaxPocLsb	= LOG2_MAX_PIC_ORDER_CNT_LSB_OFFSET + uiTmp;	// log2_max_pic_order_cnt_lsb_minus4
 
   } else if (1 == pSps->uiPocType) {
     int32_t i;
@@ -857,7 +890,11 @@
     pSps->bDeltaPicOrderAlwaysZeroFlag	= !!BsGetOneBit (pBs);	// bDeltaPicOrderAlwaysZeroFlag
     pSps->iOffsetForNonRefPic			= BsGetSe (pBs);		// iOffsetForNonRefPic
     pSps->iOffsetForTopToBottomField	= BsGetSe (pBs);		// iOffsetForTopToBottomField
-    pSps->iNumRefFramesInPocCycle		= BsGetUe (pBs);	// num_ref_frames_in_pic_order_cnt_cycle
+    uiTmp = BsGetUe (pBs);
+    WELS_CHECK_SE_UPPER_ERROR (uiTmp, SPS_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE_MAX,
+                               "num_ref_frames_in_pic_order_cnt_cycle", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS,
+                                   ERR_INFO_INVALID_NUM_REF_FRAME_IN_PIC_ORDER_CNT_CYCLE));
+    pSps->iNumRefFramesInPocCycle		= uiTmp;	// num_ref_frames_in_pic_order_cnt_cycle
     for (i = 0; i < pSps->iNumRefFramesInPocCycle; i++)
       pSps->iOffsetForRefFrame[ i ]	= BsGetSe (pBs);		// iOffsetForRefFrame[ i ]
   }
@@ -868,11 +905,39 @@
 
   pSps->iNumRefFrames	= BsGetUe (pBs);		// max_num_ref_frames
   pSps->bGapsInFrameNumValueAllowedFlag	= !!BsGetOneBit (pBs);	// bGapsInFrameNumValueAllowedFlag
-  pSps->iMbWidth		= 1 + BsGetUe (pBs);		// pic_width_in_mbs_minus1
-  pSps->iMbHeight		= 1 + BsGetUe (pBs);		// pic_height_in_map_units_minus1
+  uiTmp = BsGetUe (pBs); 		// pic_width_in_mbs_minus1
+  if (uiTmp == 0xffffffff) {
+    WelsLog (pCtx, WELS_LOG_ERROR, " pic_width_in_mbs read error!\n");
+    return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MB_SIZE_INFO);
+  }
+  pSps->iMbWidth		= PIC_WIDTH_IN_MBS_OFFSET + uiTmp;
+  if ((uint64_t) (pSps->iMbWidth * pSps->iMbWidth) > (8 * pSLevelLimits->iMaxFS)) {
+    WelsLog (pCtx, WELS_LOG_WARNING, " the pic_width_in_mbs exceeds the level limits!\n");
+  }
+  uiTmp = BsGetUe (pBs); 		// pic_height_in_map_units_minus1
+  if (uiTmp == 0xffffffff) {
+    WelsLog (pCtx, WELS_LOG_ERROR, " pic_height_in_mbs read error!\n");
+    return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MB_SIZE_INFO);
+  }
+  pSps->iMbHeight		= PIC_HEIGHT_IN_MAP_UNITS_OFFSET + uiTmp;
+  if ((uint64_t) (pSps->iMbHeight * pSps->iMbHeight) > (8 * pSLevelLimits->iMaxFS)) {
+    WelsLog (pCtx, WELS_LOG_WARNING, " the pic_height_in_mbs exceeds the level limits!\n");
+  }
   pSps->uiTotalMbCount	= pSps->iMbWidth * pSps->iMbHeight;
+  if (pSps->uiTotalMbCount > (uint32_t)pSLevelLimits->iMaxFS) {
+    WelsLog (pCtx, WELS_LOG_WARNING, " the total count of mb exceeds the level limits!\n");
+  }
+  WELS_CHECK_SE_UPPER_ERROR (pSps->iNumRefFrames, SPS_MAX_NUM_REF_FRAMES_MAX, "max_num_ref_frames",
+                             GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_NUM_REF_FRAMES));
+  // here we check max_num_ref_frames
+  uint32_t uiMaxDpbMbs = pSLevelLimits->iMaxDPBMbs;
+  uint32_t uiMaxDpbFrames = uiMaxDpbMbs / pSps->uiTotalMbCount;
+  if (uiMaxDpbFrames > SPS_MAX_NUM_REF_FRAMES_MAX)
+    uiMaxDpbFrames = SPS_MAX_NUM_REF_FRAMES_MAX;
+  if ((uint32_t)pSps->iNumRefFrames > uiMaxDpbFrames) {
+    WelsLog (pCtx, WELS_LOG_WARNING, " max_num_ref_frames exceeds level limits!\n");
+  }
   pSps->bFrameMbsOnlyFlag	= !!BsGetOneBit (pBs);	// frame_mbs_only_flag
-
   if (!pSps->bFrameMbsOnlyFlag) {
     WelsLog (pCtx, WELS_LOG_WARNING, "ParseSps(): frame_mbs_only_flag (%d) not supported.\n", pSps->bFrameMbsOnlyFlag);
     return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_MBAFF);
@@ -882,8 +947,14 @@
   if (pSps->bFrameCroppingFlag) {
     pSps->sFrameCrop.iLeftOffset	= BsGetUe (pBs);	// frame_crop_left_offset
     pSps->sFrameCrop.iRightOffset	= BsGetUe (pBs);	// frame_crop_right_offset
+    if ((pSps->sFrameCrop.iLeftOffset + pSps->sFrameCrop.iRightOffset) > ((int32_t)pSps->iMbWidth * 16 / 2)) {
+      WelsLog (pCtx, WELS_LOG_WARNING, "frame_crop_left_offset + frame_crop_right_offset exceeds limits!\n");
+    }
     pSps->sFrameCrop.iTopOffset		= BsGetUe (pBs);	// frame_crop_top_offset
     pSps->sFrameCrop.iBottomOffset	= BsGetUe (pBs);	// frame_crop_bottom_offset
+    if ((pSps->sFrameCrop.iTopOffset + pSps->sFrameCrop.iBottomOffset) > ((int32_t)pSps->iMbHeight * 16 / 2)) {
+      WelsLog (pCtx, WELS_LOG_WARNING, "frame_crop_top_offset + frame_crop_right_offset exceeds limits!\n");
+    }
   } else {
     pSps->sFrameCrop.iLeftOffset	= 0;				// frame_crop_left_offset
     pSps->sFrameCrop.iRightOffset	= 0;				// frame_crop_right_offset
@@ -957,7 +1028,7 @@
   pPps->bEntropyCodingModeFlag = !!BsGetOneBit (pBsAux);
   pPps->bPicOrderPresentFlag   = !!BsGetOneBit (pBsAux);
 
-  pPps->uiNumSliceGroups = 1 + BsGetUe (pBsAux);
+  pPps->uiNumSliceGroups = NUM_SLICE_GROUPS_OFFSET + BsGetUe (pBsAux);
 
   if (pPps->uiNumSliceGroups > MAX_SLICEGROUP_IDS) {
     return ERR_INFO_INVALID_SLICEGROUP;
@@ -974,7 +1045,7 @@
     switch (pPps->uiSliceGroupMapType) {
     case 0:
       for (iTmp = 0; iTmp < pPps->uiNumSliceGroups; iTmp++) {
-        pPps->uiRunLength[iTmp] = 1 + BsGetUe (pBsAux);
+        pPps->uiRunLength[iTmp] = RUN_LENGTH_OFFSET + BsGetUe (pBsAux);
       }
       break;
     default:
@@ -982,8 +1053,8 @@
     }
   }
 
-  pPps->uiNumRefIdxL0Active = 1 + BsGetUe (pBsAux);
-  pPps->uiNumRefIdxL1Active = 1 + BsGetUe (pBsAux);
+  pPps->uiNumRefIdxL0Active = NUM_REF_IDX_L0_DEFAULT_ACTIVE_OFFSET + BsGetUe (pBsAux);
+  pPps->uiNumRefIdxL1Active = NUM_REF_IDX_L1_DEFAULT_ACTIVE_OFFSET + BsGetUe (pBsAux);
 
   if (pPps->uiNumRefIdxL0Active > MAX_REF_PIC_COUNT ||
       pPps->uiNumRefIdxL1Active > MAX_REF_PIC_COUNT) {
@@ -998,10 +1069,15 @@
     return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_WP);
   }
 
-  pPps->iPicInitQp = 26 + BsGetSe (pBsAux);
-  pPps->iPicInitQs = 26 + BsGetSe (pBsAux);
-
+  pPps->iPicInitQp = PIC_INIT_QP_OFFSET + BsGetSe (pBsAux);
+  WELS_CHECK_SE_BOTH_ERROR (pPps->iPicInitQp, PPS_PIC_INIT_QP_QS_MIN, PPS_PIC_INIT_QP_QS_MAX, "pic_init_qp_minus26 + 26",
+                            GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_PIC_INIT_QP));
+  pPps->iPicInitQs = PIC_INIT_QS_OFFSET + BsGetSe (pBsAux);
+  WELS_CHECK_SE_BOTH_ERROR (pPps->iPicInitQs, PPS_PIC_INIT_QP_QS_MIN, PPS_PIC_INIT_QP_QS_MAX, "pic_init_qs_minus26 + 26",
+                            GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_PIC_INIT_QS));
   pPps->iChromaQpIndexOffset                  = BsGetSe (pBsAux);
+  WELS_CHECK_SE_BOTH_ERROR (pPps->iChromaQpIndexOffset, PPS_CHROMA_QP_INDEX_OFFSET_MIN, PPS_CHROMA_QP_INDEX_OFFSET_MAX,
+                            "chroma_qp_index_offset", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_CHROMA_QP_INDEX_OFFSET));
   pPps->bDeblockingFilterControlPresentFlag   = !!BsGetOneBit (pBsAux);
   pPps->bConstainedIntraPredFlag              = !!BsGetOneBit (pBsAux);
   pPps->bRedundantPicCntPresentFlag           = !!BsGetOneBit (pBsAux);
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -155,7 +155,7 @@
   int32_t iList = 0;
   const ESliceType keSt = pSh->eSliceType;
   PRefPicListReorderSyn pRefPicListReordering = &pSh->pRefPicListReordering;
-
+  PSps pSps = pSh->pSps;
   if (keSt == I_SLICE || keSt == SI_SLICE)
     return ERR_NONE;
 
@@ -166,7 +166,7 @@
     if (pRefPicListReordering->bRefPicListReorderingFlag[iList]) {
       int32_t iIdx = 0;
       do {
-        const uint8_t kuiIdc = BsGetUe (pBs);
+        const uint32_t kuiIdc = BsGetUe (pBs);
 
         //Fixed the referrence list reordering crash issue.(fault kIdc value > 3 case)---
         if ((iIdx >= MAX_REF_PIC_COUNT) || (kuiIdc > 3)) {
@@ -180,7 +180,12 @@
           return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING);
 
         if (kuiIdc == 0 || kuiIdc == 1) {
-          pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = BsGetUe (pBs);	// uiAbsDiffPicNumMinus1
+          // abs_diff_pic_num_minus1 should be in range 0 to MaxPicNum-1, MaxPicNum is derived as
+          // 2^(4+log2_max_frame_num_minus4)
+          uint32_t uiTmp = BsGetUe (pBs);
+          WELS_CHECK_SE_UPPER_ERROR_NOLOG (uiTmp, (1 << pSps->uiLog2MaxFrameNum), "abs_diff_pic_num_minus1",
+                                           GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REF_REORDERING));
+          pRefPicListReordering->sReorderingSyn[iList][iIdx].uiAbsDiffPicNumMinus1 = uiTmp;	// uiAbsDiffPicNumMinus1
         } else if (kuiIdc == 2) {
           pRefPicListReordering->sReorderingSyn[iList][iIdx].uiLongTermPicNum = BsGetUe (pBs);
         }
@@ -199,7 +204,7 @@
 int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSliceHeader pSh, PSps pSps,
                                const bool kbIdrFlag) {
   PRefPicMarking const kpRefMarking = &pSh->sRefMarking;
-
+  PRefPic pRefPic = &pCtx->sRefPic;
   if (kbIdrFlag) {
     kpRefMarking->bNoOutputOfPriorPicsFlag	= !!BsGetOneBit (pBs);
     kpRefMarking->bLongTermRefFlag			= !!BsGetOneBit (pBs);
@@ -447,6 +452,13 @@
 }
 
 #endif
+
+#define SLICE_HEADER_IDR_PIC_ID_MAX 65535
+#define SLICE_HEADER_REDUNDANT_PIC_CNT_MAX 127
+#define SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN -12
+#define SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX 12
+#define SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN -12
+#define SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX 12
 /*
  *	decode_slice_header_avc
  *	Parse slice header of bitstream in avc for storing data structure
@@ -465,6 +477,7 @@
   int32_t iRet						= ERR_NONE;
   uint8_t uiSliceType				= 0;
   uint8_t uiQualityId					= BASE_QUALITY_ID;
+  uint32_t uiTmp;
   bool	bIdrFlag					= false;
   bool	bSgChangeCycleInvolved	= false;	// involved slice group change cycle ?
 
@@ -489,6 +502,7 @@
 
   kpCurNal->sNalData.sVclNal.bSliceHeaderExtFlag	= kbExtensionFlag;
 
+  // first_mb_in_slice
   pSliceHead->iFirstMbInSlice	= BsGetUe (pBs);
 
   uiSliceType = BsGetUe (pBs);
@@ -500,7 +514,7 @@
   if (uiSliceType > 4)
     uiSliceType -= 5;
 
-  if((eNalType == NAL_UNIT_CODED_SLICE_IDR) && (uiSliceType != 2)){
+  if ((eNalType == NAL_UNIT_CODED_SLICE_IDR) && (uiSliceType != 2)) {
     WelsLog (pCtx, WELS_LOG_WARNING, "Invalid slice type(%d) in IDR picture. \n", uiSliceType);
     return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_TYPE);
   }
@@ -566,6 +580,9 @@
     WelsLog (pCtx, WELS_LOG_WARNING, "non existing SPS referenced\n");
     return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS);
   }
+  // check first_mb_in_slice
+  WELS_CHECK_SE_UPPER_ERROR ((uint32_t) (pSliceHead->iFirstMbInSlice), pSps->uiTotalMbCount, "first_mb_in_slice",
+                             GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FIRST_MB_IN_SLICE));
   pSliceHead->iFrameNum = BsGetBits (pBs, pSps->uiLog2MaxFrameNum);
 
   pSliceHead->bFieldPicFlag		= false;
@@ -584,7 +601,11 @@
                pSliceHead->iFrameNum);
       return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FRAME_NUM);
     }
-    pSliceHead->uiIdrPicId	= BsGetUe (pBs); /* uiIdrPicId */
+    uiTmp = BsGetUe (pBs);
+    // standard 7.4.3 idr_pic_id should be in range 0 to 65535, inclusive.
+    WELS_CHECK_SE_UPPER_ERROR (uiTmp, SLICE_HEADER_IDR_PIC_ID_MAX, "idr_pic_id", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
+                               ERR_INFO_INVALID_IDR_PIC_ID));
+    pSliceHead->uiIdrPicId	= uiTmp; /* uiIdrPicId */
 #ifdef LONG_TERM_REF
     pCtx->uiCurIdrPicId      = pSliceHead->uiIdrPicId;
 #endif
@@ -606,7 +627,11 @@
 
   pSliceHead->iRedundantPicCnt	= 0;
   if (pPps->bRedundantPicCntPresentFlag) {
-    pSliceHead->iRedundantPicCnt = BsGetUe (pBs);
+    uiTmp = BsGetUe (pBs);
+    // standard section 7.4.3, redundant_pic_cnt should be in range 0 to 127, inclusive.
+    WELS_CHECK_SE_UPPER_ERROR (uiTmp, SLICE_HEADER_REDUNDANT_PIC_CNT_MAX, "redundant_pic_cnt",
+                               GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_REDUNDANT_PIC_CNT));
+    pSliceHead->iRedundantPicCnt = uiTmp;
   }
 
   //set defaults, might be overriden a few line later
@@ -695,7 +720,13 @@
     }
     if (pSliceHead->uiDisableDeblockingFilterIdc != 1) {
       pSliceHead->iSliceAlphaC0Offset	= BsGetSe (pBs) * 2;	// slice_alpha_c0_offset_div2
+      WELS_CHECK_SE_BOTH_ERROR (pSliceHead->iSliceAlphaC0Offset, SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN,
+                                SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX, "slice_alpha_c0_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
+                                    ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2));
       pSliceHead->iSliceBetaOffset		= BsGetSe (pBs) * 2;	// iSliceBetaOffset
+      WELS_CHECK_SE_BOTH_ERROR (pSliceHead->iSliceBetaOffset, SLICE_HEADER_ALPHAC0_BETA_OFFSET_MIN,
+                                SLICE_HEADER_ALPHAC0_BETA_OFFSET_MAX, "slice_beta_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
+                                    ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2));
     }
   }
 
@@ -731,7 +762,14 @@
         }
         if (pSliceHeadExt->uiDisableInterLayerDeblockingFilterIdc != 1) {
           pSliceHeadExt->iInterLayerSliceAlphaC0Offset	= BsGetSe (pBs) << 1;
+          WELS_CHECK_SE_BOTH_ERROR (pSliceHeadExt->iInterLayerSliceAlphaC0Offset,
+                                    SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN, SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX,
+                                    "inter_layer_alpha_c0_offset_div2 * 2", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
+                                        ERR_INFO_INVALID_SLICE_ALPHA_C0_OFFSET_DIV2));
           pSliceHeadExt->iInterLayerSliceBetaOffset		= BsGetSe (pBs) << 1;
+          WELS_CHECK_SE_BOTH_ERROR (pSliceHeadExt->iInterLayerSliceBetaOffset, SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MIN,
+                                    SLICE_HEADER_INTER_LAYER_ALPHAC0_BETA_OFFSET_MAX, "inter_layer_slice_beta_offset_div2 * 2",
+                                    GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_SLICE_BETA_OFFSET_DIV2));
         }
       }
 
--- a/codec/decoder/core/src/parse_mb_syn_cavlc.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cavlc.cpp
@@ -985,6 +985,7 @@
                         PBitStringAux pBs) {
   PSlice pSlice				= &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer;
   PSliceHeader pSliceHeader	= &pSlice->sSliceHeaderExt.sSliceHeader;
+  PPicture* ppRefPic = pCtx->sRefPic.pRefList[LIST_0];
   int32_t iNumRefFrames		= pSliceHeader->pSps->iNumRefFrames;
   int32_t iRefCount[2];
   PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
@@ -992,7 +993,8 @@
   int32_t iMbXy = pCurDqLayer->iMbXyIndex;
   int32_t iMotionPredFlag[4];
   int16_t iMv[2] = {0};
-
+  int16_t iMinVmv = pSliceHeader->pSps->pSLevelLimits->iMinVmv;
+  int16_t iMaxVmv = pSliceHeader->pSps->pSLevelLimits->iMaxVmv;
   iMotionPredFlag[0] = iMotionPredFlag[1] = iMotionPredFlag[2] = iMotionPredFlag[3] =
                          pSlice->sSliceHeaderExt.bDefaultMotionPredFlag;
   iRefCount[0] = pSliceHeader->uiRefCount[0];
@@ -1000,13 +1002,15 @@
 
   switch (pCurDqLayer->pMbType[iMbXy]) {
   case MB_TYPE_16x16: {
-    int8_t iRefIdx = 0;
+    int32_t iRefIdx = 0;
     if (pSlice->sSliceHeaderExt.bAdaptiveMotionPredFlag) {
       iMotionPredFlag[0] = BsGetOneBit (pBs);
     }
     if (iMotionPredFlag[0] == 0) {
       iRefIdx = BsGetTe0 (pBs, iRefCount[0]);
-      if (iRefIdx < 0 || iRefIdx >= iNumRefFrames) { //error ref_idx
+      // Security check: iRefIdx should be in range 0 to num_ref_idx_l0_active_minus1, includsive
+      // ref to standard section 7.4.5.1. iRefCount[0] is 1 + num_ref_idx_l0_active_minus1.
+      if ((iRefIdx < 0) || (iRefIdx >= iRefCount[0]) || (ppRefPic[iRefIdx] == NULL)) { //error ref_idx
         return ERR_INFO_INVALID_REF_INDEX;
       }
     } else {
@@ -1017,7 +1021,7 @@
 
     iMv[0] += BsGetSe (pBs);
     iMv[1] += BsGetSe (pBs);
-
+    WELS_CHECK_SE_BOTH_WARNING (iMv[1], iMinVmv, iMaxVmv, "vertical mv");
     UpdateP16x16MotionInfo (pCurDqLayer, iRefIdx, iMv);
   }
   break;
@@ -1035,7 +1039,7 @@
         return GENERATE_ERROR_NO (ERR_LEVEL_MB_DATA, ERR_INFO_UNSUPPORTED_ILP);
       }
       iRefIdx[i] = BsGetTe0 (pBs, iRefCount[0]);
-      if (iRefIdx[i] < 0 || iRefIdx[i] >= iNumRefFrames) { //error ref_idx
+      if ((iRefIdx[i] < 0) || (iRefIdx[i] >= iRefCount[0]) || (ppRefPic[iRefIdx[i]] == NULL)) { //error ref_idx
         return ERR_INFO_INVALID_REF_INDEX;
       }
     }
@@ -1044,7 +1048,7 @@
 
       iMv[0] += BsGetSe (pBs);
       iMv[1] += BsGetSe (pBs);
-
+      WELS_CHECK_SE_BOTH_WARNING (iMv[1], iMinVmv, iMaxVmv, "vertical mv");
       UpdateP16x8MotionInfo (pCurDqLayer, iMvArray, iRefIdxArray, i << 3, iRefIdx[i], iMv);
     }
   }
@@ -1060,7 +1064,7 @@
     for (i = 0; i < 2; i++) {
       if (iMotionPredFlag[i] == 0) {
         iRefIdx[i] = BsGetTe0 (pBs, iRefCount[0]);
-        if (iRefIdx[i] < 0 || iRefIdx[i] >= iNumRefFrames) { //error ref_idx
+        if ((iRefIdx[i] < 0) || (iRefIdx[i] >= iRefCount[0]) || (ppRefPic[iRefIdx[i]] == NULL)) { //error ref_idx
           return ERR_INFO_INVALID_REF_INDEX;
         }
       } else {
@@ -1074,7 +1078,7 @@
 
       iMv[0] += BsGetSe (pBs);
       iMv[1] += BsGetSe (pBs);
-
+      WELS_CHECK_SE_BOTH_WARNING (iMv[1], iMinVmv, iMaxVmv, "vertical mv");
       UpdateP8x16MotionInfo (pCurDqLayer, iMvArray, iRefIdxArray, i << 2, iRefIdx[i], iMv);
     }
   }
@@ -1081,7 +1085,7 @@
   break;
   case MB_TYPE_8x8:
   case MB_TYPE_8x8_REF0: {
-    int8_t iRefIdx[4] = {0}, iSubPartCount[4], iPartWidth[4];
+    int32_t iRefIdx[4] = {0}, iSubPartCount[4], iPartWidth[4];
     uint32_t uiSubMbType;
 
     if (MB_TYPE_8x8_REF0 == pCurDqLayer->pMbType[iMbXy]) {
@@ -1116,7 +1120,7 @@
 
         if (iMotionPredFlag[i] == 0) {
           iRefIdx[i] = BsGetTe0 (pBs, iRefCount[0]);
-          if (iRefIdx[i] < 0 || iRefIdx[i] >= iNumRefFrames) { //error ref_idx
+          if ((iRefIdx[i] < 0) || (iRefIdx[i] >= iRefCount[0]) || (ppRefPic[iRefIdx[i]] == NULL)) { //error ref_idx
             return ERR_INFO_INVALID_REF_INDEX;
           }
 
@@ -1149,7 +1153,7 @@
 
         iMv[0] += BsGetSe (pBs);
         iMv[1] += BsGetSe (pBs);
-
+        WELS_CHECK_SE_BOTH_WARNING (iMv[1], iMinVmv, iMaxVmv, "vertical mv");
         if (SUB_MB_TYPE_8x8 == uiSubMbType) {
           ST32 (pCurDqLayer->pMv[0][iMbXy][uiScan4Idx], LD32 (iMv));
           ST32 (pCurDqLayer->pMv[0][iMbXy][uiScan4Idx + 1], LD32 (iMv));