From dc52acc7d1310f5fbd2a0f60db06f767a4698bcf Mon Sep 17 00:00:00 2001 From: Karnav Shah Date: Thu, 18 Dec 2025 15:17:35 +0530 Subject: [PATCH] Merge pull request #28200 from shahkarnav115-beep:fix-avif-null-checks imgcodecs(avif): add safety checks for AVIF decoder and encoder #28200 Add defensive checks to prevent potential null dereference in AVIF decoder and encoder paths when handling malformed input or allocation failures. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/imgcodecs/src/grfmt_avif.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_avif.cpp b/modules/imgcodecs/src/grfmt_avif.cpp index 7624515a1a..a33150e894 100644 --- a/modules/imgcodecs/src/grfmt_avif.cpp +++ b/modules/imgcodecs/src/grfmt_avif.cpp @@ -211,6 +211,10 @@ bool AvifDecoder::readHeader() { return true; decoder_ = avifDecoderCreate(); + if (!decoder_) { + CV_Error(Error::StsNoMem, "Failed to create AVIF decoder"); + return false; + } decoder_->strictFlags = AVIF_STRICT_DISABLED; if (!m_buf.empty()) { CV_Assert(m_buf.type() == CV_8UC1); @@ -226,6 +230,11 @@ bool AvifDecoder::readHeader() { decoder_); OPENCV_AVIF_CHECK_STATUS(avifDecoderParse(decoder_), decoder_); + if (!decoder_->image) { + CV_Error(Error::StsParseError, "AVIF image is null after parsing"); + return false; + } + m_width = decoder_->image->width; m_height = decoder_->image->height; m_frame_count = decoder_->imageCount; @@ -380,7 +389,6 @@ bool AvifEncoder::writeanimation(const Animation& animation, ? AVIF_ADD_IMAGE_FLAG_SINGLE : AVIF_ADD_IMAGE_FLAG_NONE; std::vector images; - std::vector imgs_scaled; for (const cv::Mat &img : animation.frames) { CV_CheckType( img.type(), @@ -388,11 +396,17 @@ bool AvifEncoder::writeanimation(const Animation& animation, ((bit_depth == 10 || bit_depth == 12) && img.depth() == CV_16U), "AVIF only supports bit depth of 8 with CV_8U input or " "bit depth of 10 or 12 with CV_16U input"); + CV_Check(img.channels(), img.channels() == 1 || img.channels() == 3 || img.channels() == 4, "AVIF only supports 1, 3, 4 channels"); - images.emplace_back(ConvertToAvif(img, do_lossless, bit_depth, m_metadata)); + auto avifImg = ConvertToAvif(img, do_lossless, bit_depth, m_metadata); + if (!avifImg) { + CV_Error(Error::StsError, "Failed to convert Mat to AVIF image"); + return false; + } + images.emplace_back(std::move(avifImg)); } for (size_t i = 0; i < images.size(); i++)