PR #25059 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25059
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25059.patch


>From f75e0bb08fae21aeca4fed59bdce78959f090ba6 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 1/9] avfilter/vf_unsharp: initialize the alpha filter
 parameters

Fixes: NULL pointer dereference
Fixes: cRljeq44cXxS
Fixes: swarm-Null-deref-when-sharpening-alpha-plane-a2779b
Regression since: 84f5583078
NULL pointer dereference Replicated through UnModified FFmpeg with ASAN
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_unsharp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c
index 6d2be4328d..85f451c82c 100644
--- a/libavfilter/vf_unsharp.c
+++ b/libavfilter/vf_unsharp.c
@@ -310,7 +310,7 @@ static int config_input(AVFilterLink *inlink)
     if (ret < 0)
         return ret;
 
-    return 0;
+    return init_filter_param(inlink->dst, &s->alpha, "alpha", inlink->w);
 }
 
 static void free_filter_param(UnsharpFilterParam *fp, int nb_threads)
@@ -331,6 +331,7 @@ static av_cold void uninit(AVFilterContext *ctx)
 
     free_filter_param(&s->luma, s->nb_threads);
     free_filter_param(&s->chroma, s->nb_threads);
+    free_filter_param(&s->alpha, s->nb_threads);
 }
 
 static int filter_frame(AVFilterLink *link, AVFrame *in)
-- 
2.52.0


>From 8564e4e7fdc0d814589c3593df1e3fd2df626c56 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 2/9] avfilter/vf_atadenoise: filter the 4th plane with its own
 thresholds and sigma

Fixes: NULL pointer dereference
Fixes: xIzHmB8ju8Nq
Fixes: swarm-NULL-dereference-on-YUVA-alpha-plane-filter-5f974b
Regression since: a50bd3a50e
NULL pointer dereference Replicated through UnModified FFmpeg with ASAN
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 doc/filters.texi            | 11 ++++++++++-
 libavfilter/vf_atadenoise.c | 23 ++++++++++-------------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 04496d338f..9eeb5fdcd3 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -8689,6 +8689,14 @@ Valid range is 0 to 0.3.
 Set threshold B for 3rd plane. Default is 0.04.
 Valid range is 0 to 5.
 
+@item 3a
+Set threshold A for 4th plane. Default is 0.02.
+Valid range is 0 to 0.3.
+
+@item 3b
+Set threshold B for 4th plane. Default is 0.04.
+Valid range is 0 to 5.
+
 Threshold A is designed to react on abrupt changes in the input signal and
 threshold B is designed to react on continuous changes in the input signal.
 
@@ -8710,7 +8718,8 @@ will continue processing other side of frames if they are 
equal or below thresho
 @item 0s
 @item 1s
 @item 2s
-Set sigma for 1st plane, 2nd plane or 3rd plane. Default is 32767.
+@item 3s
+Set sigma for 1st plane, 2nd plane, 3rd plane or 4th plane. Default is 32767.
 Valid range is from 0 to 32767.
 This options controls weight for each pixel in radius defined by size.
 Default value means every pixel have same weight.
diff --git a/libavfilter/vf_atadenoise.c b/libavfilter/vf_atadenoise.c
index 7773df5615..9e2bee1ce5 100644
--- a/libavfilter/vf_atadenoise.c
+++ b/libavfilter/vf_atadenoise.c
@@ -76,6 +76,8 @@ static const AVOption atadenoise_options[] = {
     { "1b", "set threshold B for 2nd plane", OFFSET(fthrb[1]), 
AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 5.0, FLAGS },
     { "2a", "set threshold A for 3rd plane", OFFSET(fthra[2]), 
AV_OPT_TYPE_FLOAT, {.dbl=0.02}, 0, 0.3, FLAGS },
     { "2b", "set threshold B for 3rd plane", OFFSET(fthrb[2]), 
AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 5.0, FLAGS },
+    { "3a", "set threshold A for 4th plane", OFFSET(fthra[3]), 
AV_OPT_TYPE_FLOAT, {.dbl=0.02}, 0, 0.3, FLAGS },
+    { "3b", "set threshold B for 4th plane", OFFSET(fthrb[3]), 
AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 5.0, FLAGS },
     { "s",  "set how many frames to use",    OFFSET(size),     
AV_OPT_TYPE_INT,   {.i64=9},   5, SIZE, VF    },
     { "p",  "set what planes to filter",     OFFSET(planes),   
AV_OPT_TYPE_FLAGS, {.i64=7},    0, 15,  FLAGS },
     { "a",  "set variant of algorithm",      
OFFSET(algorithm),AV_OPT_TYPE_INT,   {.i64=PARALLEL},  0, NB_ATAA-1, FLAGS, 
.unit = "a" },
@@ -84,6 +86,7 @@ static const AVOption atadenoise_options[] = {
     { "0s", "set sigma for 1st plane",       OFFSET(sigma[0]), 
AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
     { "1s", "set sigma for 2nd plane",       OFFSET(sigma[1]), 
AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
     { "2s", "set sigma for 3rd plane",       OFFSET(sigma[2]), 
AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
+    { "3s", "set sigma for 4th plane",       OFFSET(sigma[3]), 
AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS },
     { NULL }
 };
 
@@ -409,16 +412,12 @@ static int config_input(AVFilterLink *inlink)
             s->dsp.filter_row[p] = s->algorithm == PARALLEL ? fweight_row16 : 
fweight_row16_serial;
     }
 
-    s->thra[0] = s->fthra[0] * (1 << depth) - 1;
-    s->thra[1] = s->fthra[1] * (1 << depth) - 1;
-    s->thra[2] = s->fthra[2] * (1 << depth) - 1;
-    s->thrb[0] = s->fthrb[0] * (1 << depth) - 1;
-    s->thrb[1] = s->fthrb[1] * (1 << depth) - 1;
-    s->thrb[2] = s->fthrb[2] * (1 << depth) - 1;
-
     for (int p = 0; p < s->nb_planes; p++) {
         float sigma = s->radius * s->sigma[p];
 
+        s->thra[p] = s->fthra[p] * (1 << depth) - 1;
+        s->thrb[p] = s->fthrb[p] * (1 << depth) - 1;
+
         s->weights[p][s->radius] = 1.f;
         for (int n = 1; n <= s->radius; n++) {
             s->weights[p][s->radius + n] =
@@ -473,12 +472,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame 
*buf)
         for (i = 0; i < s->size; i++) {
             AVFrame *frame = ff_bufqueue_peek(&s->q, i);
 
-            s->data[0][i] = frame->data[0];
-            s->data[1][i] = frame->data[1];
-            s->data[2][i] = frame->data[2];
-            s->linesize[0][i] = frame->linesize[0];
-            s->linesize[1][i] = frame->linesize[1];
-            s->linesize[2][i] = frame->linesize[2];
+            for (int p = 0; p < s->nb_planes; p++) {
+                s->data[p][i] = frame->data[p];
+                s->linesize[p][i] = frame->linesize[p];
+            }
         }
 
         td.in = in; td.out = out;
-- 
2.52.0


>From c50b55930460b85b54b277143b5c135c224b0479 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 3/9] avfilter/vf_crop: keep the x/y expressions when the new
 ones fail to parse

This is not a security issue.

Fixes: 3yfFBPXxhEts
Fixes: 
swarm-NULL-pexpr-dereference-after-failed-x-y-runtime-reconfiguration-e3e672
Regression since: d2b78fe6b7
NULL pointer dereference Replicated through UnModified FFmpeg with ASAN
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_crop.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index e06be77302..f25e0564aa 100644
--- a/libavfilter/vf_crop.c
+++ b/libavfilter/vf_crop.c
@@ -225,17 +225,21 @@ fail_expr:
 static int config_input(AVFilterLink *link)
 {
     CropContext *s = link->dst->priv;
+    AVExpr *x_pexpr = NULL, *y_pexpr = NULL;
 
     s->var_values[VAR_X] = NAN;
     s->var_values[VAR_Y] = NAN;
+    if (av_expr_parse(&x_pexpr, s->x_expr, var_names,
+                      NULL, NULL, NULL, NULL, 0, link->dst) < 0 ||
+        av_expr_parse(&y_pexpr, s->y_expr, var_names,
+                      NULL, NULL, NULL, NULL, 0, link->dst) < 0) {
+        av_expr_free(x_pexpr);
+        return AVERROR(EINVAL);
+    }
     av_expr_free(s->x_pexpr);
     av_expr_free(s->y_pexpr);
-    s->x_pexpr = s->y_pexpr = NULL;
-    if (av_expr_parse(&s->x_pexpr, s->x_expr, var_names,
-                      NULL, NULL, NULL, NULL, 0, link->dst) < 0 ||
-        av_expr_parse(&s->y_pexpr, s->y_expr, var_names,
-                      NULL, NULL, NULL, NULL, 0, link->dst) < 0)
-        return AVERROR(EINVAL);
+    s->x_pexpr = x_pexpr;
+    s->y_pexpr = y_pexpr;
 
     return config_crop_area(link);
 }
-- 
2.52.0


>From e563c17f95694485728655a90d0cff8eb130509b Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 4/9] avcodec/decode: use avcodec_get_hw_config() in
 avcodec_default_get_format()

This is not a security issue.

Fixes: e5BUoyG1Jo3N
Fixes: swarm-NULL-pointer-dereference-in-hw_configs-iteration-0b77cc
Regression since: 67e81d79cc
NULL pointer member access Replicated through API with UBSAN
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavcodec/decode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 627ad9420a..96da70fb7e 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1019,7 +1019,7 @@ enum AVPixelFormat avcodec_default_get_format(struct 
AVCodecContext *avctx,
         AVHWDeviceContext *device_ctx =
             (AVHWDeviceContext*)avctx->hw_device_ctx->data;
         for (i = 0;; i++) {
-            config = &ffcodec(avctx->codec)->hw_configs[i]->public;
+            config = avcodec_get_hw_config(avctx->codec, i);
             if (!config)
                 break;
             if (!(config->methods &
-- 
2.52.0


>From e766542a13cf3846d29cc3c8107aab6c465d1135 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 5/9] avformat/rtmpproto: reject a llnw authentication
 challenge without a nonce

This is not a security issue.

Fixes: 6lFLlG49gRxf
Fixes: swarm-NULL-pointer-dereference-via-snprintf-s-with-NULL-nonce-83e8f3
Regression since: c1ea44c54d
NULL nonce passed to snprintf() Replicated through UnModified FFmpeg with a 
local RTMP server (the reconnect carried nonce=(null))
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/rtmpproto.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index 785455e06d..392c559090 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -1760,8 +1760,7 @@ static int do_llnw_auth(RTMPContext *rt, const char 
*user, const char *nonce)
     av_md5_init(md5);
     av_md5_update(md5, hashstr1, strlen(hashstr1));
     av_md5_update(md5, ":", 1);
-    if (nonce)
-        av_md5_update(md5, nonce, strlen(nonce));
+    av_md5_update(md5, nonce, strlen(nonce));
     av_md5_update(md5, ":", 1);
     av_md5_update(md5, nc, strlen(nc));
     av_md5_update(md5, ":", 1);
@@ -1864,6 +1863,10 @@ static int handle_connect_error(URLContext *s, const 
char *desc)
         if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
             return ret;
     } else {
+        if (!nonce) {
+            av_log(s, AV_LOG_ERROR, "No nonce in the llnw authentication 
challenge\n");
+            return AVERROR_UNKNOWN;
+        }
         if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
             return ret;
     }
-- 
2.52.0


>From 6753c616462439e603e93233e91e13c75063526e Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 6/9] avformat/rtmpdh: fail bn_hex2bn() when bn_new() fails
 with GMP and mbedTLS

This is not a security issue.

Fixes: d9RoImPBG3x8
Fixes: swarm-NULL-q1-passed-to-bn_modexp-when-GMP-MbedTLS-alloc-fails-c4db13
Regression since: 78efc69e7c (GMP), 62f5c9d68b (mbedTLS)
NULL bignum passed to bn_modexp() Replicated through Modified FFmpeg with ASAN 
(GMP and mbedTLS builds, the q1 allocation in ff_dh_generate_public_key() made 
to fail)
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/rtmpdh.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavformat/rtmpdh.c b/libavformat/rtmpdh.c
index 6a6c2ccd87..fb7aaf07c0 100644
--- a/libavformat/rtmpdh.c
+++ b/libavformat/rtmpdh.c
@@ -95,7 +95,7 @@
         if (bn)                                     \
             ret = (mpz_set_str(bn, buf, 16) == 0);  \
         else                                        \
-            ret = 1;                                \
+            ret = 0;                                \
     } while (0)
 #define bn_random(bn, num_bits)                       \
     do {                                              \
@@ -198,7 +198,7 @@ static int bn_modexp(FFBigNum bn, FFBigNum y, FFBigNum q, 
FFBigNum p)
         if (bn)                                     \
             ret = (mbedtls_mpi_read_string(bn, 16, buf) == 0);  \
         else                                        \
-            ret = 1;                                \
+            ret = 0;                                \
     } while (0)
 #define bn_random(bn, num_bits)                     \
     do {                                            \
-- 
2.52.0


>From 93e5d114204b8a154e5f6765810fc5db2074ed43 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Tue, 13 Oct 2026 06:39:23 +0200
Subject: [PATCH 7/9] avcodec/mediacodecdec: escape a 00 00 0x sequence ending
 on the last byte of a parameter set

This is not a security issue.

Fixes: D8dV7mhIc12c
Fixes: swarm-Off-by-one-error-in-NALU-escape-loop-459f43
Regression since: 88d9c30cf5
Verified with h2645_ps_to_nalu() compiled standalone; the decoder itself was 
not run (Android only)
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavcodec/mediacodecdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c
index 89f8ed54a8..0551370a54 100644
--- a/libavcodec/mediacodecdec.c
+++ b/libavcodec/mediacodecdec.c
@@ -99,7 +99,7 @@ static int h2645_ps_to_nalu(const uint8_t *src, int src_size, 
uint8_t **out, int
 
     /* Escape 0x00, 0x00, 0x0{0-3} pattern */
     for (i = 4; i < *out_size; i++) {
-        if (i < *out_size - 3 &&
+        if (i < *out_size - 2 &&
             p[i + 0] == 0 &&
             p[i + 1] == 0 &&
             p[i + 2] <= 3) {
-- 
2.52.0


>From 8244474c6442d3fa0e448b8dc9a186c0c95c7c69 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Tue, 13 Oct 2026 06:40:15 +0200
Subject: [PATCH 8/9] avfilter/vf_libvmaf: reject a feature config without a
 name

This is not a security issue.

Fixes: 1QLxiyziAd9N
Fixes: swarm-NULL-feature_name-dereferenced-in-parse_features-129e69
Regression since: 3d29724c00
NULL feature name Replicated through UnModified FFmpeg (the error message read 
"(null)")
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_libvmaf.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c
index 3ab67d3dba..4771541664 100644
--- a/libavfilter/vf_libvmaf.c
+++ b/libavfilter/vf_libvmaf.c
@@ -239,30 +239,36 @@ static int parse_features(AVFilterContext *ctx)
     }
 
     for (unsigned i = 0; i < dict_cnt; i++) {
-        char *feature_name = NULL;
+        const AVDictionaryEntry *name = av_dict_get(dict[i], "name", NULL,
+                                                    AV_DICT_MATCH_CASE);
         VmafFeatureDictionary *feature_opts_dict = NULL;
         const AVDictionaryEntry *e = NULL;
 
+        if (!name) {
+            av_log(ctx, AV_LOG_ERROR, "feature without a name: %s\n",
+                   s->feature_cfg);
+            err = AVERROR(EINVAL);
+            goto exit;
+        }
+
         while (e = av_dict_iterate(dict[i], e)) {
-            if (!strcmp(e->key, "name")) {
-                feature_name = e->value;
+            if (!strcmp(e->key, "name"))
                 continue;
-            }
 
             err = vmaf_feature_dictionary_set(&feature_opts_dict, e->key,
                                               e->value);
             if (err) {
                 av_log(ctx, AV_LOG_ERROR,
                        "could not set feature option: %s.%s=%s\n",
-                       feature_name, e->key, e->value);
+                       name->value, e->key, e->value);
                 goto exit;
             }
         }
 
-        err = vmaf_use_feature(s->vmaf, feature_name, feature_opts_dict);
+        err = vmaf_use_feature(s->vmaf, name->value, feature_opts_dict);
         if (err) {
             av_log(ctx, AV_LOG_ERROR,
-                   "problem during vmaf_use_feature: %s\n", feature_name);
+                   "problem during vmaf_use_feature: %s\n", name->value);
             goto exit;
         }
     }
-- 
2.52.0


>From 8c2a8f7a151f0157c77f7c9df62743fbda8a06fc Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 13 Oct 2026 06:40:15 +0200
Subject: [PATCH 9/9] avcodec/nvdec: attach the hw_frames_ctx before the unmap
 buffer owns the mapped frame

This is not a security issue.

Fixes: DPSu3J80jQZN
Fixes: 
swarm-NULL-deref-in-nvdec_unmap_mapped_frame-when-av_buffer_replace-fails-5c28b7
Regression since: 767f53533a
NULL pointer dereference Replicated through Modified FFmpeg with ASAN 
(av_buffer_replace() made to fail for one frame)
Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavcodec/nvdec.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c
index f0ae2130c2..d2c176e4f9 100644
--- a/libavcodec/nvdec.c
+++ b/libavcodec/nvdec.c
@@ -922,6 +922,10 @@ static int nvdec_retrieve_data(void *logctx, AVFrame 
*frame)
     if (ret < 0)
         goto finish;
 
+    ret = av_buffer_replace(&frame->hw_frames_ctx, 
decoder->real_hw_frames_ref);
+    if (ret < 0)
+        goto copy_fail;
+
     unmap_data = av_mallocz(sizeof(*unmap_data));
     if (!unmap_data) {
         ret = AVERROR(ENOMEM);
@@ -936,10 +940,6 @@ static int nvdec_retrieve_data(void *logctx, AVFrame 
*frame)
         goto copy_fail;
     }
 
-    ret = av_buffer_replace(&frame->hw_frames_ctx, 
decoder->real_hw_frames_ref);
-    if (ret < 0)
-        goto copy_fail;
-
     unmap_data->idx = cf->idx;
     unmap_data->decoder = av_refstruct_ref(cf->decoder);
 
@@ -953,12 +953,8 @@ static int nvdec_retrieve_data(void *logctx, AVFrame 
*frame)
     goto finish;
 
 copy_fail:
-    if (!frame->buf[1]) {
-        CHECK_CU(decoder->cvdl->cuvidUnmapVideoFrame(decoder->decoder, 
devptr));
-        av_freep(&unmap_data);
-    } else {
-        av_buffer_unref(&frame->buf[1]);
-    }
+    CHECK_CU(decoder->cvdl->cuvidUnmapVideoFrame(decoder->decoder, devptr));
+    av_freep(&unmap_data);
 
 finish:
     CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
-- 
2.52.0

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

Reply via email to