[PR] avcodec/dovi: multiple fixes (PR #23911)

michaelni via ffmpeg-devel <[email protected]> Sat, 25 Jul 2026 12:36:29 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178498298963.59.16203621923235731569@29965ddac10e>
PR #23911 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23911
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23911.patch


>From 3548661ea4af200104e7ff0f85e8013e493a622a Mon Sep 17 00:00:00 2001
From: Kenan Alghythee <[email protected]>
Date: Sat, 11 Jul 2026 16:57:38 +0200
Subject: [PATCH 1/5] avcodec/bsf/dovi_rpu: handle update_rpu() returning no
 RPU

Fixes: out of array access
Fixes: SUcVEyk7r3Gc
Found-by: Kenan Alghythee <[email protected]>
---
 libavcodec/bsf/dovi_rpu.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libavcodec/bsf/dovi_rpu.c b/libavcodec/bsf/dovi_rpu.c
index 88da4417b5..e8aa3eadcd 100644
--- a/libavcodec/bsf/dovi_rpu.c
+++ b/libavcodec/bsf/dovi_rpu.c
@@ -99,6 +99,8 @@ static int dovi_rpu_update_fragment_hevc(AVBSFContext *bsf, AVPacket *pkt,
     ret = update_rpu(bsf, pkt, 0, nal->data + 2, nal->data_size - 2, &rpu, &rpu_size);
     if (ret < 0)
         return ret;
+    if (!rpu || rpu_size <= 0)
+        return 0;
 
     /* NAL unit header + NAL prefix */
     if (rpu_size + 3 <= nal->data_size && av_buffer_is_writable(nal->data_ref)) {
@@ -158,6 +160,10 @@ static int dovi_rpu_update_fragment_av1(AVBSFContext *bsf, AVPacket *pkt,
                          &rpu, &rpu_size);
         if (ret < 0)
             return ret;
+        if (!rpu || rpu_size <= 1) {
+            av_free(rpu);
+            continue;
+        }
 
         ref = av_buffer_create(rpu, rpu_size, av_buffer_default_free, NULL, 0);
         if (!ref) {
-- 
2.52.0


>From 314a840cd0960809f02a85c4ded1f0f5c7f41347 Mon Sep 17 00:00:00 2001
From: Kenan Alghythee <[email protected]>
Date: Sat, 11 Jul 2026 16:57:38 +0200
Subject: [PATCH 2/5] avcodec/dovi_rpuenc: validate vdr_rpu_id from the input
 metadata

Fixes: out of array access
Fixes: SUcVEyk7r3Gc
Found-by: Kenan Alghythee <[email protected]>
---
 libavcodec/dovi_rpuenc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index dc63c68405..9d3db33071 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -599,6 +599,10 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
         dv_md_compression = AV_DOVI_COMPRESSION_NONE;
 
     vdr_rpu_id = mapping->vdr_rpu_id;
+    if (vdr_rpu_id < 0 || vdr_rpu_id > DOVI_MAX_DM_ID) {
+        av_log(s->logctx, AV_LOG_ERROR, "Invalid VDR RPU id %d\n", vdr_rpu_id);
+        return AVERROR_INVALIDDATA;
+    }
     use_prev_vdr_rpu = 0;
 
     if (!s->vdr[vdr_rpu_id]) {
-- 
2.52.0


>From f8b42ad77709cae2ccb318283e4ba9ee0258cee3 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Sat, 11 Jul 2026 17:01:30 +0200
Subject: [PATCH 3/5] avcodec/dovi_rpudec: bound num_x/y_partitions

Fixes: out of array access
Fixes: SUcVEyk7r3Gc
Found-by: Kenan Alghythee <[email protected]>
---
 libavcodec/dovi_rpudec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index d210ba52cf..ba4e7cd214 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -582,6 +582,8 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
 
         mapping->num_x_partitions = get_ue_golomb_long(gb) + 1;
         mapping->num_y_partitions = get_ue_golomb_long(gb) + 1;
+        VALIDATE(mapping->num_x_partitions, 1, 0xFFFF);
+        VALIDATE(mapping->num_y_partitions, 1, 0xFFFF);
         /* End of rpu_data_header(), start of vdr_rpu_data_payload() */
 
         for (int c = 0; c < 3; c++) {
-- 
2.52.0


>From 37faa69b6ffd13dc9e59a4c26efe9f78faf94675 Mon Sep 17 00:00:00 2001
From: Kenan Alghythee <[email protected]>
Date: Wed, 22 Jul 2026 23:48:29 +0200
Subject: [PATCH 4/5] avcodec/dovi_rpuenc: validate the data mapping before
 generation

Fixes: out of array access
Fixes: SUcVEyk7r3Gc
Found-by: Kenan Alghythee <[email protected]>
---
 libavcodec/dovi_rpuenc.c | 86 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 9d3db33071..8b7a74f313 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -367,6 +367,87 @@ static inline void put_se_coef(PutBitContext *pb, const AVDOVIRpuDataHeader *hdr
     }
 }
 
+static int validate_ue_golomb_value(uint64_t value)
+{
+    return value <= 0xFFFE;
+}
+
+static int validate_se_golomb_value(int64_t value)
+{
+    return value >= -0x7FFF && value <= 0x7FFF;
+}
+
+static int validate_ue_coef(const AVDOVIRpuDataHeader *hdr, uint64_t coef)
+{
+    if (hdr->coef_log2_denom >= 63)
+        return 0;
+    return validate_ue_golomb_value(coef >> hdr->coef_log2_denom);
+}
+
+static int validate_se_coef(const AVDOVIRpuDataHeader *hdr, int64_t coef)
+{
+    if (hdr->coef_log2_denom >= 63)
+        return 0;
+    return validate_se_golomb_value(coef >> hdr->coef_log2_denom);
+}
+
+static int validate_mapping_for_generation(const AVDOVIRpuDataHeader *hdr,
+                                           const AVDOVIDataMapping *mapping)
+{
+    if (!mapping->num_x_partitions || mapping->num_x_partitions > 0xFFFF ||
+        !mapping->num_y_partitions || mapping->num_y_partitions > 0xFFFF)
+        return 0;
+
+    for (int c = 0; c < 3; c++) {
+        const AVDOVIReshapingCurve *curve = &mapping->curves[c];
+
+        if (curve->num_pivots < 2 || curve->num_pivots > AV_DOVI_MAX_PIECES + 1)
+            return 0;
+
+        for (int i = 1; i < curve->num_pivots; i++)
+            if (curve->pivots[i] < curve->pivots[i - 1])
+                return 0;
+
+        for (int i = 0; i < curve->num_pivots - 1; i++) {
+            switch (curve->mapping_idc[i]) {
+            case AV_DOVI_MAPPING_POLYNOMIAL:
+                if (curve->poly_order[i] < 1 || curve->poly_order[i] > 2)
+                    return 0;
+                for (int k = 0; k <= curve->poly_order[i]; k++)
+                    if (!validate_se_coef(hdr, curve->poly_coef[i][k]))
+                        return 0;
+                break;
+            case AV_DOVI_MAPPING_MMR:
+                if (curve->mmr_order[i] < 1 || curve->mmr_order[i] > 3)
+                    return 0;
+                if (!validate_se_coef(hdr, curve->mmr_constant[i]))
+                    return 0;
+                for (int j = 0; j < curve->mmr_order[i]; j++)
+                    for (int k = 0; k < 7; k++)
+                        if (!validate_se_coef(hdr, curve->mmr_coef[i][j][k]))
+                            return 0;
+                break;
+            default:
+                return 0;
+            }
+        }
+    }
+
+    if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
+        if (mapping->nlq_method_idc != AV_DOVI_NLQ_LINEAR_DZ)
+            return 0;
+        for (int c = 0; c < 3; c++) {
+            const AVDOVINLQParams *nlq = &mapping->nlq[c];
+            if (!validate_ue_coef(hdr, nlq->vdr_in_max) ||
+                !validate_ue_coef(hdr, nlq->linear_deadzone_slope) ||
+                !validate_ue_coef(hdr, nlq->linear_deadzone_threshold))
+                return 0;
+        }
+    }
+
+    return 1;
+}
+
 static int av_q2den(AVRational q, int den)
 {
     if (!q.den || q.den == den)
@@ -595,6 +676,11 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
         return AVERROR_INVALIDDATA;
     }
 
+    if (!validate_mapping_for_generation(hdr, mapping)) {
+        av_log(s->logctx, AV_LOG_ERROR, "Coefficient out of range for RPU\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     if (!(flags & FF_DOVI_COMPRESS_RPU))
         dv_md_compression = AV_DOVI_COMPRESSION_NONE;
 
-- 
2.52.0


>From 4e4a06a98715d853b7af180bb45cc9ae2bad7d4b Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Wed, 22 Jul 2026 22:46:55 +0200
Subject: [PATCH 5/5] avcodec/dovi_rpuenc: normalize vdr_dm_metadata_present to
 0/1

---
 libavcodec/dovi_rpuenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 8b7a74f313..d0abcc0d9e 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -726,7 +726,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
             return AVERROR(ENOMEM);
     }
 
-    vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
+    vdr_dm_metadata_present = !!memcmp(color, &ff_dovi_color_default, sizeof(*color));
     if (metadata->num_ext_blocks)
         vdr_dm_metadata_present = 1;
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]