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);
+}
+