From 931bd1694e92d0e15097d4862d33408f5cd4eb7b Mon Sep 17 00:00:00 2001 From: Takashi Yano Date: Wed, 10 Jul 2024 21:55:28 +0900 Subject: [PATCH] Avoid signed integer (POC) overflow in decoder_core.c Addresses: https://github.com/cisco/openh264/issues/3745 --- codec/decoder/core/src/decoder_core.cpp | 24 ++++++++++++++++++++--- codec/decoder/plus/src/welsDecoderExt.cpp | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/codec/decoder/core/src/decoder_core.cpp b/codec/decoder/core/src/decoder_core.cpp index 9d8f5eaa2..2e280dcb8 100644 --- a/codec/decoder/core/src/decoder_core.cpp +++ b/codec/decoder/core/src/decoder_core.cpp @@ -1079,16 +1079,34 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb = 0; pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb = 0; } + /* We shoud not expect that overflow in signed integer returns wrapped- + around result. C/C++ standard states the result is undefined. */ int32_t pocMsb; if (pocLsb < pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb && pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb - pocLsb >= iMaxPocLsb / 2) - pocMsb = pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb + iMaxPocLsb; + { + if (INT32_MAX - iMaxPocLsb < pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb) + /* Will overflow. Emulate wraparound result. */ + pocMsb = (pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb - INT32_MAX - 1) + (INT32_MIN + iMaxPocLsb); + else + pocMsb = pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb + iMaxPocLsb; + } else if (pocLsb > pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb && pocLsb - pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb > iMaxPocLsb / 2) - pocMsb = pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb - iMaxPocLsb; + { + if (INT32_MIN + iMaxPocLsb > pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb) + /* Will overflow. Emulate wraparound result. */ + pocMsb = (pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb - INT32_MIN) + (INT32_MAX - iMaxPocLsb + 1); + else + pocMsb = pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb - iMaxPocLsb; + } else pocMsb = pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb; - pSliceHead->iPicOrderCntLsb = pocMsb + pocLsb; + if (INT32_MAX - pocLsb < pocMsb) + /* Will overflow. Emulate wraparound result. */ + pSliceHead->iPicOrderCntLsb = (pocMsb - INT32_MAX - 1) + (INT32_MIN + pocLsb); + else + pSliceHead->iPicOrderCntLsb = pocMsb + pocLsb; if (pPps->bPicOrderPresentFlag && !pSliceHead->bFieldPicFlag) { pSliceHead->iPicOrderCntLsb += pSliceHead->iDeltaPicOrderCntBottom; diff --git a/codec/decoder/plus/src/welsDecoderExt.cpp b/codec/decoder/plus/src/welsDecoderExt.cpp index 08f2a2743..e22314a40 100644 --- a/codec/decoder/plus/src/welsDecoderExt.cpp +++ b/codec/decoder/plus/src/welsDecoderExt.cpp @@ -1055,7 +1055,7 @@ void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx, int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC; int32_t iLastSeqNum = pCtx != NULL ? pCtx->iSeqNum : m_sPictInfoList[m_iLastBufferedIdx].iSeqNum; isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32 - && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1) + && m_sReoderingStatus.iMinPOC <= m_sReoderingStatus.iLastWrittenPOC + 1) || m_sReoderingStatus.iMinPOC < iLastPOC || m_sReoderingStatus.iMinSeqNum - iLastSeqNum < 0; }