shithub: openh264

Download patch

ref: 2e5f1b213478bfe830ad846088d6ad14c1400dd5
parent: 3efc32a15e9773b6023805033d7b74f75862b8a6
parent: 0fc550221585d252f2beb3b6720469875673910b
author: huili2 <huili2@cisco.com>
date: Wed Feb 27 09:04:37 EST 2019

Merge pull request #3100 from xiaotiansf/NewBugzilla2

Fix Issues 13030 and 13039 in oss-fuzz.

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -78,13 +78,14 @@
   /**
   * Errors derived from bitstream parsing
   */
-  dsErrorFree           = 0x00,   ///< bit stream error-free
-  dsFramePending        = 0x01,   ///< need more throughput to generate a frame output,
-  dsRefLost             = 0x02,   ///< layer lost at reference frame with temporal id 0
-  dsBitstreamError      = 0x04,   ///< error bitstreams(maybe broken internal frame) the decoder cared
-  dsDepLayerLost        = 0x08,   ///< dependented layer is ever lost
-  dsNoParamSets         = 0x10,   ///< no parameter set NALs involved
-  dsDataErrorConcealed  = 0x20,   ///< current data error concealed specified
+  dsErrorFree = 0x00,   ///< bit stream error-free
+  dsFramePending = 0x01,   ///< need more throughput to generate a frame output,
+  dsRefLost = 0x02,   ///< layer lost at reference frame with temporal id 0
+  dsBitstreamError = 0x04,   ///< error bitstreams(maybe broken internal frame) the decoder cared
+  dsDepLayerLost = 0x08,   ///< dependented layer is ever lost
+  dsNoParamSets = 0x10,   ///< no parameter set NALs involved
+  dsDataErrorConcealed = 0x20,   ///< current data error concealed specified
+  dsRefListNullPtrs = 0x40, ///<ref picure list contains null ptrs within uiRefCount range
 
   /**
   * Errors derived from logic level
--- a/codec/decoder/core/src/decode_slice.cpp
+++ b/codec/decoder/core/src/decode_slice.cpp
@@ -56,6 +56,28 @@
 
 extern PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const int32_t kiPicHeight);
 
+static bool CheckRefPics (const PWelsDecoderContext& pCtx) {
+  int32_t listCount = 1;
+  if (pCtx->eSliceType == B_SLICE) {
+    ++listCount;
+  }
+  for (int32_t list = LIST_0; list < listCount; ++list) {
+    int32_t shortRefCount = pCtx->sRefPic.uiShortRefCount[list];
+    for (int32_t refIdx = 0; refIdx < shortRefCount; ++refIdx) {
+      if (!pCtx->sRefPic.pShortRefList[list][refIdx]) {
+        return false;
+      }
+    }
+    int32_t longRefCount = pCtx->sRefPic.uiLongRefCount[list];
+    for (int32_t refIdx = 0; refIdx < longRefCount; ++refIdx) {
+      if (!pCtx->sRefPic.pLongRefList[list][refIdx]) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx) {
   PDqLayer pCurLayer = pCtx->pCurDqLayer;
   PSlice pCurSlice = &pCurLayer->sLayerInfo.sSliceInLayer;
@@ -318,7 +340,10 @@
     WelsMbIntraPredictionConstruction (pCtx, pCurLayer, 1);
   } else if (IS_INTER (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) { //InterMB
     if (0 == pCurLayer->pCbp[pCurLayer->iMbXyIndex]) { //uiCbp==0 include SKIP
-      WelsMbInterPrediction (pCtx, pCurLayer);
+      if (!CheckRefPics (pCtx)) {
+        return ERR_INFO_MB_RECON_FAIL;
+      }
+      return WelsMbInterPrediction (pCtx, pCurLayer);
     } else {
       WelsMbInterConstruction (pCtx, pCurLayer);
     }
@@ -2783,7 +2808,7 @@
   return ERR_NONE;
 }
 
-void WelsBlockFuncInit (SBlockFunc*   pFunc,  int32_t iCpu) {
+void WelsBlockFuncInit (SBlockFunc*    pFunc,  int32_t iCpu) {
   pFunc->pWelsSetNonZeroCountFunc   = WelsNonZeroCount_c;
   pFunc->pWelsBlockZero16x16Func    = WelsBlockZero16x16_c;
   pFunc->pWelsBlockZero8x8Func      = WelsBlockZero8x8_c;
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -165,6 +165,24 @@
   return ERR_NONE;
 }
 
+static void ResetRefPicReferences (const PWelsDecoderContext& pCtx, const PPicture& inPPic) {
+  //seach and reset the references of deleted references.
+  for (int32_t list = LIST_0; list < LIST_A; ++list) {
+    int32_t refIdx = 0;
+    PPicture pPic = pCtx->sRefPic.pRefList[list][refIdx];
+    while (refIdx < MAX_DPB_COUNT && pPic != NULL) {
+      ++refIdx;
+      int32_t ref = 0;
+      while (ref < MAX_DPB_COUNT && *pPic->pRefPic[ref] != NULL) {
+        if (*pPic->pRefPic[ref] == inPPic) {
+          *pPic->pRefPic[ref] = NULL;
+        }
+        ++ref;
+      }
+    }
+  }
+}
+
 static int32_t DecreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
                                 const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
   PPicBuff pPicOldBuf = *ppPicBuf;
@@ -212,6 +230,7 @@
   for (iPicIdx = iDelIdx; iPicIdx < kiOldSize; iPicIdx++) {
     if (iPrevPicIdx != iPicIdx) {
       if (pPicOldBuf->ppPic[iPicIdx] != NULL) {
+        ResetRefPicReferences (pCtx, pPicOldBuf->ppPic[iPicIdx]);
         FreePicture (pPicOldBuf->ppPic[iPicIdx], pMa);
         pPicOldBuf->ppPic[iPicIdx] = NULL;
       }
@@ -826,7 +845,8 @@
   const int32_t kiPicWidth    = kiMbWidth << 4;
   const int32_t kiPicHeight   = kiMbHeight << 4;
   //fix Bugzilla Bug1479656 reallocate temp dec picture
-  if (pCtx->pTempDec != NULL) {
+  if (pCtx->pTempDec != NULL && (pCtx->pTempDec->iWidthInPixel != kiPicWidth
+                                 || pCtx->pTempDec->iHeightInPixel != kiPicHeight)) {
     FreePicture (pCtx->pTempDec, pCtx->pMemAlign);
     pCtx->pTempDec = AllocPicture (pCtx, pCtx->pSps->iMbWidth << 4, pCtx->pSps->iMbHeight << 4);
   }
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -2720,7 +2720,10 @@
       DecodeFrameConstruction (pCtx, ppDst, pDstInfo);
       pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future use
       if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
-        MarkECFrameAsRef (pCtx);
+        if (MarkECFrameAsRef (pCtx) == ERR_INFO_INVALID_PTR) {
+          pCtx->iErrorCode |= dsRefListNullPtrs;
+          return false;
+        }
       }
     } else if (pCtx->pParam->bParseOnly) { //clear parse only internal data status
       pCtx->pParserBsInfo->iNalNum = 0;
--- a/codec/decoder/core/src/manage_dec_ref.cpp
+++ b/codec/decoder/core/src/manage_dec_ref.cpp
@@ -792,6 +792,9 @@
   if (pRefPic->uiShortRefCount[LIST_0] > 0) {
     // Check the duplicate frame_num in short ref list
     for (int32_t iPos = 0; iPos < pRefPic->uiShortRefCount[LIST_0]; iPos++) {
+      if (!pRefPic->pShortRefList[LIST_0][iPos]) {
+        return ERR_INFO_INVALID_PTR;
+      }
       if (pPic->iFrameNum == pRefPic->pShortRefList[LIST_0][iPos]->iFrameNum) {
         // Replace the previous ref pic with the new one with the same frame_num
         pRefPic->pShortRefList[LIST_0][iPos] = pPic;
@@ -819,6 +822,9 @@
     pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = pPic;
   } else {
     for (i = 0; i < pRefPic->uiLongRefCount[LIST_0]; i++) {
+      if (!pRefPic->pLongRefList[LIST_0][i]) {
+        return ERR_INFO_INVALID_PTR;
+      }
       if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pPic->iLongTermFrameIdx) {
         break;
       }
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -593,6 +593,12 @@
       }
       return dsErrorFree;
     }
+    if (m_pDecContext->iErrorCode & dsRefListNullPtrs) {
+      if (ResetDecoder()) {
+        return dsRefListNullPtrs;
+      }
+      return dsErrorFree;
+    }
     //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
     if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
         (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) {