Commit 5afa9190 for openh264

commit 5afa91907ec612e2fb71633b7b88ae4e83362496
Author: BenzhengZhang <140143892+BenzhengZhang@users.noreply.github.com>
Date:   Thu Jul 16 14:14:29 2026 +0800

    decoder: initialize iPicBuffIdx and validate before picture buffer indexing (#3965)

    * decoder: initialize iPicBuffIdx and validate before picture buffer indexing

    * decoder: add UT for reordering pic buffer idx reset

    ---------

    Co-authored-by: benzzhan <benzzhan@cisco.com>

diff --git a/codec/decoder/core/src/decoder.cpp b/codec/decoder/core/src/decoder.cpp
index f52f9792..65da8a45 100644
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -302,6 +302,7 @@ void ResetReorderingPictureBuffers (PPictReoderingStatus pPictReoderingStatus, P
     pPictReoderingStatus->iLargestBufferedPicIndex = 0;
     for (int32_t i = 0; i < pictInfoListCount; ++i) {
       pPictInfo[i].iPOC = IMinInt32;
+      pPictInfo[i].iPicBuffIdx = -1; //ensure a deterministic invalid sentinel so error-path decoding cannot leave heap garbage
     }
     pPictInfo->sBufferInfo.iBufferStatus = 0;
 		pPictReoderingStatus->bHasBSlice = false;
diff --git a/codec/decoder/plus/src/welsDecoderExt.cpp b/codec/decoder/plus/src/welsDecoderExt.cpp
index 08e037a3..06d11217 100644
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -1126,10 +1126,13 @@ void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx
     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
     if (pCtx || m_pPicBuff) {
       PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
-      PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
-      --pPic->iRefCount;
-      if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
-        pPic->pSetUnRef(pPic);
+      int32_t iPicBuffIdx = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx;
+      if (pPicBuff != NULL && iPicBuffIdx >= 0 && iPicBuffIdx < pPicBuff->iCapacity) {
+        PPicture pPic = pPicBuff->ppPic[iPicBuffIdx];
+        --pPic->iRefCount;
+        if (pPic->iRefCount <= 0 && pPic->pSetUnRef)
+          pPic->pSetUnRef(pPic);
+      }
     }
     --m_sReoderingStatus.iNumOfPicts;
   }
diff --git a/test/decoder/DecUT_ParseSyntax.cpp b/test/decoder/DecUT_ParseSyntax.cpp
index f1322762..8ad21665 100644
--- a/test/decoder/DecUT_ParseSyntax.cpp
+++ b/test/decoder/DecUT_ParseSyntax.cpp
@@ -442,4 +442,57 @@ TEST_F (DecoderParseSyntaxTest, DecoderParseSyntaxTestAll) {
   TestSpecificBsError();
 }

+TEST (DecoderReorderingBufferTest, PartialResetInitializesPicBuffIdx) {
+  SPictReoderingStatus sStatus;
+  SPictInfo sPictInfo[16];
+
+  memset (&sStatus, 0, sizeof (sStatus));
+  memset (&sPictInfo, 0, sizeof (sPictInfo));
+
+  for (int32_t i = 0; i < 16; ++i) {
+    sPictInfo[i].iPOC = i + 100;
+    sPictInfo[i].iPicBuffIdx = i + 200;
+  }
+  sPictInfo[0].sBufferInfo.iBufferStatus = 1;
+  sStatus.iLargestBufferedPicIndex = 3;
+
+  ResetReorderingPictureBuffers (&sStatus, sPictInfo, false);
+
+  for (int32_t i = 0; i <= 3; ++i) {
+    EXPECT_EQ (IMinInt32, sPictInfo[i].iPOC);
+    EXPECT_EQ (-1, sPictInfo[i].iPicBuffIdx);
+  }
+
+  // Partial reset should not touch entries beyond iLargestBufferedPicIndex.
+  EXPECT_EQ (104, sPictInfo[4].iPOC);
+  EXPECT_EQ (204, sPictInfo[4].iPicBuffIdx);
+  EXPECT_EQ (0, sPictInfo[0].sBufferInfo.iBufferStatus);
+  EXPECT_FALSE (sStatus.bHasBSlice);
+  EXPECT_EQ (0, sStatus.iNumOfPicts);
+  EXPECT_EQ (0, sStatus.iLargestBufferedPicIndex);
+}
+
+TEST (DecoderReorderingBufferTest, FullResetInitializesPicBuffIdx) {
+  SPictReoderingStatus sStatus;
+  SPictInfo sPictInfo[16];
+
+  memset (&sStatus, 0, sizeof (sStatus));
+  memset (&sPictInfo, 0, sizeof (sPictInfo));
+
+  for (int32_t i = 0; i < 16; ++i) {
+    sPictInfo[i].iPOC = i + 300;
+    sPictInfo[i].iPicBuffIdx = i + 400;
+  }
+  sStatus.iLargestBufferedPicIndex = 1;
+
+  ResetReorderingPictureBuffers (&sStatus, sPictInfo, true);
+
+  for (int32_t i = 0; i < 16; ++i) {
+    EXPECT_EQ (IMinInt32, sPictInfo[i].iPOC);
+    EXPECT_EQ (-1, sPictInfo[i].iPicBuffIdx);
+  }
+  EXPECT_FALSE (sStatus.bHasBSlice);
+  EXPECT_EQ (0, sStatus.iLargestBufferedPicIndex);
+}
+