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


>From 14380e060aaf3d45b0ea638c19d6d4d84cc71a33 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Thu, 15 Oct 2026 03:53:08 +0200
Subject: [PATCH 01/12] avfilter/vf_avgblur: compute max * area in 64bit

Fixes: out of array read
Fixes: BxsBdfl8050I
Fixes: 
swarm-Signed-integer-overflow-in-build_lut-slow-check-enables-heap-OOB-read-ba3309
Regression since: a7fc78c1a6
Out of array read Replicated through UnModified FFmpeg with ASAN

Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_avgblur.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_avgblur.c b/libavfilter/vf_avgblur.c
index 3bd4faa5f6..66c046471e 100644
--- a/libavfilter/vf_avgblur.c
+++ b/libavfilter/vf_avgblur.c
@@ -174,7 +174,7 @@ static void build_lut(AVFilterContext *ctx, int max)
     const int area = (2 * s->radiusV + 1) * (2 * s->radius + 1);
 
     s->area = area;
-    if (max * area >= FF_ARRAY_ELEMS(s->lut))
+    if ((int64_t)max * area >= FF_ARRAY_ELEMS(s->lut))
         return;
 
     for (int i = 0, j = 0, k = 0; i < max * area; i++, j++) {
@@ -234,7 +234,7 @@ static void averageiir2d(AVFilterContext *ctx, AVFrame *in, 
AVFrame *out, int pl
     AverageBlurContext *s = ctx->priv;
     const int width = s->planewidth[plane];
     const int height = s->planeheight[plane];
-    const int slow = (s->max * s->area) >= FF_ARRAY_ELEMS(s->lut);
+    const int slow = ((int64_t)s->max * s->area) >= FF_ARRAY_ELEMS(s->lut);
     ThreadData td;
 
     td.width = width;
-- 
2.54.0


>From 363b94a55972cf50192603b72a19f5793500a142 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Thu, 15 Oct 2026 04:01:57 +0200
Subject: [PATCH 02/12] avformat/idroqdec: skip the whole body of a repeated
 RoQ_INFO chunk

The RoQ player in the Quake III Arena source (code/client/cl_cin.c) also
continues after the declared size of every RoQ_INFO chunk.

Fixes: yyLBi9GsHV9w
Fixes: swarm-RoQ_INFO-re-entry-skips-fixed-size-ignoring-chunk_size-e7709a
Stream desynchronization Replicated through UnModified FFmpeg

Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/idroqdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c
index 861338ceec..76d96196ba 100644
--- a/libavformat/idroqdec.c
+++ b/libavformat/idroqdec.c
@@ -142,7 +142,7 @@ static int roq_read_packet(AVFormatContext *s,
                 break;
             }
             /* don't care about this chunk anymore */
-            avio_skip(pb, RoQ_CHUNK_PREAMBLE_SIZE);
+            avio_skip(pb, chunk_size);
             break;
 
         case RoQ_QUAD_CODEBOOK:
-- 
2.54.0


>From 98eae281668d6260753ef1e30b822361b9068871 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 04:03:02 +0200
Subject: [PATCH 03/12] avformat/idroqdec: compute the codebook and VQ packet
 size in 64bit

Fixes: yyLBi9GsHV9w
Packet size wraparound Replicated through UnModified FFmpeg

Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/idroqdec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c
index 76d96196ba..ad904b42b4 100644
--- a/libavformat/idroqdec.c
+++ b/libavformat/idroqdec.c
@@ -99,7 +99,7 @@ static int roq_read_packet(AVFormatContext *s,
     RoqDemuxContext *roq = s->priv_data;
     AVIOContext *pb = s->pb;
     int ret = 0;
-    unsigned int chunk_size;
+    int64_t chunk_size;
     unsigned int chunk_type;
     unsigned int codebook_size;
     unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
@@ -154,7 +154,7 @@ static int roq_read_packet(AVFormatContext *s,
             avio_skip(pb, codebook_size);
             if ((ret = ffio_read_size(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) 
< 0)
                 return ret;
-            chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
+            chunk_size = (int64_t)AV_RL32(&preamble[2]) + 
RoQ_CHUNK_PREAMBLE_SIZE * 2 +
                 codebook_size;
 
             if (chunk_size > INT_MAX)
-- 
2.54.0


>From 26fb03a862178952884c6003271cf6d0f07b121d Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 04:06:26 +0200
Subject: [PATCH 04/12] avfilter/vf_pad: do the x/y range check and centering
 in 64bit

Fixes: Ilayk1MzOixN
Fixes: swarm-Signed-integer-overflow-in-pad-x-y-bounds-check-499261
Regression since: 57c3670896
Signed integer overflow Replicated through UnModified FFmpeg with UBSAN

Found-by: zhang xingxing <[email protected]>
The report suggested, among other options, widening the comparison.
The overflow in the centering was found during review of the fixes for the 
report.

Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_pad.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c
index a3436bb2d6..4891cf2518 100644
--- a/libavfilter/vf_pad.c
+++ b/libavfilter/vf_pad.c
@@ -180,10 +180,10 @@ static int config_input(AVFilterLink *inlink)
         goto eval_fail;
     s->x = var_values[VAR_X] = res;
 
-    if (s->x < 0 || s->x + inlink->w > s->w)
-        s->x = var_values[VAR_X] = (s->w - inlink->w) / 2;
-    if (s->y < 0 || s->y + inlink->h > s->h)
-        s->y = var_values[VAR_Y] = (s->h - inlink->h) / 2;
+    if (s->x < 0 || (int64_t)s->x + inlink->w > s->w)
+        s->x = var_values[VAR_X] = ((int64_t)s->w - inlink->w) / 2;
+    if (s->y < 0 || (int64_t)s->y + inlink->h > s->h)
+        s->y = var_values[VAR_Y] = ((int64_t)s->h - inlink->h) / 2;
 
     s->w    = ff_draw_round_to_sub(&s->draw, 0, -1, s->w);
     s->h    = ff_draw_round_to_sub(&s->draw, 1, -1, s->h);
-- 
2.54.0


>From df628b13030b58aa3e48b7d260366e4fb14a8dc9 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 04:06:26 +0200
Subject: [PATCH 05/12] avfilter/vf_pad_vaapi: do the x/y range check and
 centering in 64bit

Fixes: Ilayk1MzOixN
Fixes: swarm-Signed-integer-overflow-in-pad-x-y-bounds-check-499261
Regression since: 42eb10ecc6

Found-by: zhang xingxing <[email protected]>
The report suggested, among other options, widening the comparison.
The overflow in the centering was found during review of the fixes for the 
report.

Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_pad_vaapi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavfilter/vf_pad_vaapi.c b/libavfilter/vf_pad_vaapi.c
index 5e9dad3065..a6ceae5b75 100644
--- a/libavfilter/vf_pad_vaapi.c
+++ b/libavfilter/vf_pad_vaapi.c
@@ -133,10 +133,10 @@ static int pad_vaapi_config_output(AVFilterLink *outlink)
         return ret;
     ctx->x = var_values[VAR_X] = res;
 
-    if (ctx->x < 0 || ctx->x + inlink->w > ctx->w)
-        ctx->x = var_values[VAR_X] = (ctx->w - inlink->w) / 2;
-    if (ctx->y < 0 || ctx->y + inlink->h > ctx->h)
-        ctx->y = var_values[VAR_Y] = (ctx->h - inlink->h) / 2;
+    if (ctx->x < 0 || (int64_t)ctx->x + inlink->w > ctx->w)
+        ctx->x = var_values[VAR_X] = ((int64_t)ctx->w - inlink->w) / 2;
+    if (ctx->y < 0 || (int64_t)ctx->y + inlink->h > ctx->h)
+        ctx->y = var_values[VAR_Y] = ((int64_t)ctx->h - inlink->h) / 2;
 
     /* sanity check params */
     if (ctx->w < inlink->w || ctx->h < inlink->h) {
-- 
2.54.0


>From 850fc52acccf052ac259135dac16331c4fbf751e Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 04:34:32 +0200
Subject: [PATCH 06/12] avformat/sctp: return AVERROR_EOF when the peer closes
 the association

Fixes: WoBBcuySgSTx
Fixes: swarm-sctp_read-returns-2-on-graceful-close-never-signalling-EOF-2a7ba0
Endless loop Replicated through UnModified FFmpeg

Found-by: zhang xingxing <[email protected]>
The report suggested not adding the stream id size when recvmsg() returns 0.
The case without max_streams was found during triage of the report.

Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/sctp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libavformat/sctp.c b/libavformat/sctp.c
index 0efac12d96..ed132f1851 100644
--- a/libavformat/sctp.c
+++ b/libavformat/sctp.c
@@ -309,17 +309,19 @@ static int sctp_read(URLContext *h, uint8_t *buf, int 
size)
     }
 
     if (s->max_streams) {
-        if (size < 2)
+        if (size <= 2)
             return AVERROR(EINVAL);
 
         /*StreamId is introduced as a 2byte code into the stream*/
         struct sctp_sndrcvinfo info = { 0 };
         ret = ff_sctp_recvmsg(s->fd, buf + 2, size - 2, NULL, 0, &info, 0);
         AV_WB16(buf, info.sinfo_stream);
-        ret = ret < 0 ? ret : ret + 2;
+        ret = ret <= 0 ? ret : ret + 2;
     } else
         ret = recv(s->fd, buf, size, 0);
 
+    if (!ret)
+        return AVERROR_EOF;
     return ret < 0 ? ff_neterrno() : ret;
 }
 
-- 
2.54.0


>From 925c50e4f2ff108fe8580ef1c3b6dc6f08c48f5a Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Thu, 15 Oct 2026 04:35:44 +0200
Subject: [PATCH 07/12] avcodec/tiff_common: do not size the metadata bprint
 from count

Fixes: 0gCI9NJKm3tO
Fixes: swarm-Signed-overflow-of-10-count-100-count-in-av_bprint_init-f6bdbe
Regression since: b7ba7cbd6e
Signed integer overflow Replicated through UnModified FFmpeg with UBSAN

Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavcodec/tiff_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/tiff_common.c b/libavcodec/tiff_common.c
index 265f843031..c4c672632a 100644
--- a/libavcodec/tiff_common.c
+++ b/libavcodec/tiff_common.c
@@ -108,7 +108,7 @@ int ff_tadd_doubles_metadata(int count, const char *name, 
const char *sep,
     if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t))
         return AVERROR_INVALIDDATA;
 
-    av_bprint_init(&bp, 10 * count, 100 * count);
+    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
 
     for (i = 0; i < count; i++) {
         av_bprintf(&bp, "%s%.15g", auto_sep(count, sep, i, 4), 
ff_tget_double(gb, le));
@@ -129,7 +129,7 @@ int ff_tadd_shorts_metadata(int count, const char *name, 
const char *sep,
     if (bytestream2_get_bytes_left(gb) < count * sizeof(int16_t))
         return AVERROR_INVALIDDATA;
 
-    av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED);
+    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
 
     for (i = 0; i < count; i++) {
         int v = is_signed ? (int16_t)ff_tget_short(gb, le) :  
ff_tget_short(gb, le);
-- 
2.54.0


>From 253ece0df43583e8502ab912a7dcf52021dfb357 Mon Sep 17 00:00:00 2001
From: zhang xingxing <[email protected]>
Date: Thu, 15 Oct 2026 04:46:24 +0200
Subject: [PATCH 08/12] avfilter/vf_stack: use ff_slice_pos() for the per-slice
 input range

Fixes: GIRN0tvt58WQ
Fixes: swarm-Signed-integer-overflow-in-process_slice-slice-computation-b29bec
Regression since: 631f7acc6c
Out of array read Replicated through UnModified FFmpeg with ASAN

Found-by: zhang xingxing <[email protected]>
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_stack.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
index 6e9ac60a56..19c4b2c147 100644
--- a/libavfilter/vf_stack.c
+++ b/libavfilter/vf_stack.c
@@ -148,8 +148,8 @@ static int process_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
     StackContext *s = ctx->priv;
     AVFrame *out = arg;
     AVFrame **in = s->frames;
-    const int start = (s->nb_inputs *  job   ) / nb_jobs;
-    const int end   = (s->nb_inputs * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(s->nb_inputs, job, nb_jobs);
+    const int end   = ff_slice_pos(s->nb_inputs, job + 1, nb_jobs);
 
     for (int i = start; i < end; i++) {
         StackItem *item = &s->items[i];
-- 
2.54.0


>From 830c67c8de1d0acd8549eea0f17ee55c2fdc9424 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 04:46:24 +0200
Subject: [PATCH 09/12] avfilter: use ff_slice_pos() in the remaining slice
 threaded filters

This is a behavior preserving change for all non-overflowing cases.

Found during triage of the security report GIRN0tvt58WQ

Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_framerate.c      |  4 ++--
 libavfilter/vf_hflip.c          |  4 ++--
 libavfilter/vf_lenscorrection.c |  8 ++++----
 libavfilter/vf_perspective.c    |  8 ++++----
 libavfilter/vf_readeia608.c     |  4 ++--
 libavfilter/vf_rotate.c         |  4 ++--
 libavfilter/vsrc_gradients.c    | 12 ++++++------
 libavfilter/vsrc_sierpinski.c   |  8 ++++----
 libavfilter/vsrc_testsrc.c      |  4 ++--
 9 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c
index 468042e7db..d603483c29 100644
--- a/libavfilter/vf_framerate.c
+++ b/libavfilter/vf_framerate.c
@@ -101,8 +101,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
     int plane;
 
     for (plane = 0; plane < 4 && src1->data[plane] && src2->data[plane]; 
plane++) {
-        const int start = (s->height[plane] *  job   ) / nb_jobs;
-        const int end   = (s->height[plane] * (job+1)) / nb_jobs;
+        const int start = ff_slice_pos(s->height[plane], job, nb_jobs);
+        const int end   = ff_slice_pos(s->height[plane], job + 1, nb_jobs);
         uint8_t *src1_data = src1->data[plane] + start * src1->linesize[plane];
         uint8_t *src2_data = src2->data[plane] + start * src2->linesize[plane];
         uint8_t *dst_data  = work->data[plane] + start * work->linesize[plane];
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index 8f8dd14240..2c1c2c4120 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -93,8 +93,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int 
job, int nb_jobs)
     for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
         const int width  = s->planewidth[plane] / s->bayer_plus1;
         const int height = s->planeheight[plane];
-        const int start = (height *  job   ) / nb_jobs;
-        const int end   = (height * (job+1)) / nb_jobs;
+        const int start = ff_slice_pos(height, job, nb_jobs);
+        const int end   = ff_slice_pos(height, job + 1, nb_jobs);
 
         step = s->max_step[plane];
 
diff --git a/libavfilter/vf_lenscorrection.c b/libavfilter/vf_lenscorrection.c
index 15c2e99e4b..945e456c41 100644
--- a/libavfilter/vf_lenscorrection.c
+++ b/libavfilter/vf_lenscorrection.c
@@ -86,8 +86,8 @@ static int filter##name##_slice(AVFilterContext *ctx, void 
*arg, int job,      \
     const int w = rect->planewidth[plane], h = rect->planeheight[plane];       
\
     const int xcenter = rect->cx * w;                                          
\
     const int ycenter = rect->cy * h;                                          
\
-    const int start = (h *  job   ) / nb_jobs;                                 
\
-    const int end   = (h * (job+1)) / nb_jobs;                                 
\
+    const int start = ff_slice_pos(h, job, nb_jobs);                           
\
+    const int end   = ff_slice_pos(h, job + 1, nb_jobs);                       
\
     const int inlinesize = in->linesize[plane] / sizeof(type);                 
\
     const int outlinesize = out->linesize[plane] / sizeof(type);               
\
     const type *indata = (const type *)in->data[plane];                        
\
@@ -128,8 +128,8 @@ static int filter##name##_slice_bilinear(AVFilterContext 
*ctx, void *arg,      \
     const int w = rect->planewidth[plane], h = rect->planeheight[plane];       
\
     const int xcenter = rect->cx * w;                                          
\
     const int ycenter = rect->cy * h;                                          
\
-    const int start = (h *  job   ) / nb_jobs;                                 
\
-    const int end   = (h * (job+1)) / nb_jobs;                                 
\
+    const int start = ff_slice_pos(h, job, nb_jobs);                           
\
+    const int end   = ff_slice_pos(h, job + 1, nb_jobs);                       
\
     const int inlinesize = in->linesize[plane] / sizeof(type);                 
\
     const int outlinesize = out->linesize[plane] / sizeof(type);               
\
     const type *indata = (const type *)in->data[plane];                        
\
diff --git a/libavfilter/vf_perspective.c b/libavfilter/vf_perspective.c
index 58510f6f13..184de78d36 100644
--- a/libavfilter/vf_perspective.c
+++ b/libavfilter/vf_perspective.c
@@ -286,8 +286,8 @@ static int resample_cubic(AVFilterContext *ctx, void *arg,
     int h = td->h;
     int hsub = td->hsub;
     int vsub = td->vsub;
-    int start = (h * job) / nb_jobs;
-    int end   = (h * (job+1)) / nb_jobs;
+    int start = ff_slice_pos(h, job, nb_jobs);
+    int end   = ff_slice_pos(h, job + 1, nb_jobs);
     const int linesize = s->linesize[0];
     int x, y;
 
@@ -365,8 +365,8 @@ static int resample_linear(AVFilterContext *ctx, void *arg,
     int h = td->h;
     int hsub = td->hsub;
     int vsub = td->vsub;
-    int start = (h * job) / nb_jobs;
-    int end   = (h * (job+1)) / nb_jobs;
+    int start = ff_slice_pos(h, job, nb_jobs);
+    int end   = ff_slice_pos(h, job + 1, nb_jobs);
     const int linesize = s->linesize[0];
     int x, y;
 
diff --git a/libavfilter/vf_readeia608.c b/libavfilter/vf_readeia608.c
index 605ca86d17..86e9019356 100644
--- a/libavfilter/vf_readeia608.c
+++ b/libavfilter/vf_readeia608.c
@@ -446,8 +446,8 @@ static int extract_lines(AVFilterContext *ctx, void *arg,
     ReadEIA608Context *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
     const int h = s->end - s->start + 1;
-    const int start = (h * job) / nb_jobs;
-    const int end   = (h * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(h, job, nb_jobs);
+    const int end   = ff_slice_pos(h, job + 1, nb_jobs);
     AVFrame *in = arg;
 
     for (int i = start; i < end; i++) {
diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c
index 740acfe3bd..4640f175bb 100644
--- a/libavfilter/vf_rotate.c
+++ b/libavfilter/vf_rotate.c
@@ -420,8 +420,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
     const int plane = td->plane;
     const int xi = td->xi, yi = td->yi;
     const int c = td->c, s = td->s;
-    const int start = (outh *  job   ) / nb_jobs;
-    const int end   = (outh * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(outh, job, nb_jobs);
+    const int end   = ff_slice_pos(outh, job + 1, nb_jobs);
     int xprime = td->xprime + start * s;
     int yprime = td->yprime + start * c;
     int i, j, x, y;
diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c
index cb1b73773f..d6294d3309 100644
--- a/libavfilter/vsrc_gradients.c
+++ b/libavfilter/vsrc_gradients.c
@@ -254,8 +254,8 @@ static int draw_gradients_slice(AVFilterContext *ctx, void 
*arg, int job, int nb
     AVFrame *frame = arg;
     const int width  = frame->width;
     const int height = frame->height;
-    const int start = (height *  job   ) / nb_jobs;
-    const int end   = (height * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(height, job, nb_jobs);
+    const int end   = ff_slice_pos(height, job + 1, nb_jobs);
     const ptrdiff_t linesize = frame->linesize[0] / 4;
     uint32_t *dst = (uint32_t *)frame->data[0] + start * linesize;
     const int type = s->type;
@@ -278,8 +278,8 @@ static int draw_gradients_slice16(AVFilterContext *ctx, 
void *arg, int job, int
     AVFrame *frame = arg;
     const int width  = frame->width;
     const int height = frame->height;
-    const int start = (height *  job   ) / nb_jobs;
-    const int end   = (height * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(height, job, nb_jobs);
+    const int end   = ff_slice_pos(height, job + 1, nb_jobs);
     const ptrdiff_t linesize = frame->linesize[0] / 8;
     uint64_t *dst = (uint64_t *)frame->data[0] + start * linesize;
     const int type = s->type;
@@ -302,8 +302,8 @@ static int draw_gradients_slice32_planar(AVFilterContext 
*ctx, void *arg, int jo
     AVFrame *frame = arg;
     const int width  = frame->width;
     const int height = frame->height;
-    const int start = (height *  job   ) / nb_jobs;
-    const int end   = (height * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(height, job, nb_jobs);
+    const int end   = ff_slice_pos(height, job + 1, nb_jobs);
     const ptrdiff_t linesize_g = frame->linesize[0] / 4;
     const ptrdiff_t linesize_b = frame->linesize[1] / 4;
     const ptrdiff_t linesize_r = frame->linesize[2] / 4;
diff --git a/libavfilter/vsrc_sierpinski.c b/libavfilter/vsrc_sierpinski.c
index c9134184a5..77a0c6cdc2 100644
--- a/libavfilter/vsrc_sierpinski.c
+++ b/libavfilter/vsrc_sierpinski.c
@@ -91,8 +91,8 @@ static int draw_triangle_slice(AVFilterContext *ctx, void 
*arg, int job, int nb_
     AVFrame *frame = arg;
     const int width  = frame->width;
     const int height = frame->height;
-    const int start = (height *  job   ) / nb_jobs;
-    const int end   = (height * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(height, job, nb_jobs);
+    const int end   = ff_slice_pos(height, job + 1, nb_jobs);
     uint8_t *dst = frame->data[0] + start * frame->linesize[0];
 
     for (int y = start; y < end; y++) {
@@ -116,8 +116,8 @@ static int draw_carpet_slice(AVFilterContext *ctx, void 
*arg, int job, int nb_jo
     AVFrame *frame = arg;
     const int width  = frame->width;
     const int height = frame->height;
-    const int start = (height *  job   ) / nb_jobs;
-    const int end   = (height * (job+1)) / nb_jobs;
+    const int start = ff_slice_pos(height, job, nb_jobs);
+    const int end   = ff_slice_pos(height, job + 1, nb_jobs);
     uint8_t *dst = frame->data[0] + start * frame->linesize[0];
 
     for (int y = start; y < end; y++) {
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index 697b94d4e8..1beb7d7e4a 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -2131,8 +2131,8 @@ static int zoneplate_fill_slice_##name(AVFilterContext 
*ctx,       \
     const int ky = test->ky, kx = test->kx, kxy = test->kxy;       \
     const int lut_mask = (1 << test->lut_precision) - 1;           \
     const int nkt2t = kt2 * t * t, nktt = kt * t;                  \
-    const int start = (h *  job   ) / nb_jobs;                     \
-    const int end   = (h * (job+1)) / nb_jobs;                     \
+    const int start = ff_slice_pos(h, job, nb_jobs);               \
+    const int end   = ff_slice_pos(h, job + 1, nb_jobs);           \
     const ptrdiff_t ylinesize = frame->linesize[0] / sizeof(type); \
     const ptrdiff_t ulinesize = frame->linesize[1] / sizeof(type); \
     const ptrdiff_t vlinesize = frame->linesize[2] / sizeof(type); \
-- 
2.54.0


>From ca98b587f9c7cc80213a34d3cfb2cf4224b1bd36 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 04:58:55 +0200
Subject: [PATCH 10/12] avformat/idroqdec: continue after the declared size of
 the first RoQ_INFO chunk

Stream desynchronization Replicated through UnModified FFmpeg

Found during review of the fixes for the security report yyLBi9GsHV9w
Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavformat/idroqdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c
index ad904b42b4..c67724b128 100644
--- a/libavformat/idroqdec.c
+++ b/libavformat/idroqdec.c
@@ -139,7 +139,7 @@ static int roq_read_packet(AVFormatContext *s,
                     return ret;
                 st->codecpar->width  = roq->width  = AV_RL16(preamble);
                 st->codecpar->height = roq->height = AV_RL16(preamble + 2);
-                break;
+                chunk_size -= RoQ_CHUNK_PREAMBLE_SIZE;
             }
             /* don't care about this chunk anymore */
             avio_skip(pb, chunk_size);
-- 
2.54.0


>From ea4bfd207d9cd7b8b88dbb14c188223f3bd135ee Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 05:00:32 +0200
Subject: [PATCH 11/12] avfilter/vf_stack: reject a grid with more than INT_MAX
 cells

Regression since: aa8905a1b1
NULL pointer dereference Replicated through UnModified FFmpeg with ASAN

Found during review of the fixes for the security report GIRN0tvt58WQ

Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_stack.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
index 19c4b2c147..04a335858b 100644
--- a/libavfilter/vf_stack.c
+++ b/libavfilter/vf_stack.c
@@ -116,8 +116,11 @@ static av_cold int init(AVFilterContext *ctx)
             }
         }
 
-        if (is_grid)
+        if (is_grid) {
+            if (s->nb_grid_rows > INT_MAX / s->nb_grid_columns)
+                return AVERROR(EINVAL);
             s->nb_inputs = s->nb_grid_rows * s->nb_grid_columns;
+        }
     }
 
     s->frames = av_calloc(s->nb_inputs, sizeof(*s->frames));
-- 
2.54.0


>From 4531bc72cbeb956e33c92efbeecb519080cc872a Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Thu, 15 Oct 2026 15:51:52 +0200
Subject: [PATCH 12/12] avfilter/vf_codecview: compute the arrow head length in
 64bit

Fixes: division by zero
Fixes: signed integer overflow
Fixes: NaN to int conversion
Fixes: 2qHh10XPbgiO
Fixes: swarm-Signed-integer-overflow-in-draw_arrow-length-calc-8f1f15
Division by zero Replicated through UnModified FFmpeg with ASAN
Signed integer overflow Replicated through UnModified FFmpeg with UBSAN
NaN to int conversion Replicated through UnModified FFmpeg with UBSAN

Found-by: zhang xingxing <[email protected]>
The report suggested doing the shift in a wider unsigned type.

Signed-off-by: Michael Niedermayer <[email protected]>
---
 libavfilter/vf_codecview.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c
index f20056b91b..cd445e4e9c 100644
--- a/libavfilter/vf_codecview.c
+++ b/libavfilter/vf_codecview.c
@@ -190,7 +190,7 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex,
     if (dx * dx + dy * dy > 3 * 3) {
         int rx =  dx + dy;
         int ry = -dx + dy;
-        int length = sqrt((rx * rx + ry * ry) << 8);
+        int length = sqrt((rx * (int64_t)rx + ry * (int64_t)ry) << 8);
 
         // FIXME subpixel accuracy
         rx = ROUNDED_DIV(rx * (3 << 4), length);
-- 
2.54.0

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

Reply via email to