This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 8f38703323ad52a4a56bf9729067fe3c7a35df4f
Author:     Niklas Haas <[email protected]>
AuthorDate: Mon May 18 15:27:50 2026 +0200
Commit:     Niklas Haas <[email protected]>
CommitDate: Tue Jun 2 15:36:42 2026 +0200

    swscale/ops_dispatch: calculate correct slice line count for tail copy
    
    These loops were both assuming that `h` lines need to be copied; but this
    varies. First of all, for plane subsampling; but more importantly, when
    vertically scaling, the input line count may be substantially lower than the
    actual line count.
    
    This fixes an out-of-bounds read/write when vertically upscaling with a tail
    buffer.
    
    Verifiable via e.g.:
      make libswscale/tests/swscale
      valgrind -- libswscale/tests/swscale -s 63x63 -src yuv444p -dst rgb24 \
                  -flags unstable -align_src 1 -align_dst 1
    
    (As well as the SSIM scores, which drop from ~e-5 to ~e-3 without this fix)
    
    Sponsored-by: Sovereign Tech Fund
    Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/ops_dispatch.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c
index 8b04ef1c96..5745a2aff2 100644
--- a/libswscale/ops_dispatch.c
+++ b/libswscale/ops_dispatch.c
@@ -143,6 +143,18 @@ static inline void get_row_data(const SwsOpPass *p, const 
int y_dst,
         out[i] = base->out[i] + (y_dst >> base->out_sub_y[i]) * 
base->out_stride[i];
 }
 
+static inline int get_lines_in(const SwsOpPass *p, const int y, const int h,
+                               const int plane)
+{
+    const SwsOpExec *base = &p->exec_base;
+    if (!p->offsets_y)
+        return h >> base->in_sub_y[plane];
+
+    const int y0 = p->offsets_y[y] >> base->in_sub_y[plane];
+    const int y1 = p->offsets_y[y + h - 1] >> base->in_sub_y[plane];
+    return y1 - y0 + 1;
+}
+
 static inline size_t pixel_bytes(size_t pixels, int pixel_bits,
                                  enum AVRounding rounding)
 {
@@ -423,8 +435,9 @@ static void op_pass_run(const SwsFrame *out, const SwsFrame 
*in, const int y,
 
     for (int i = 0; i < p->planes_in; i++) {
         if (memcpy_in) {
+            const int lines = get_lines_in(p, y, h, i);
             copy_lines((uint8_t *) tail.in[i], tail.in_stride[i],
-                       exec.in[i], exec.in_stride[i], h, p->tail_size_in);
+                       exec.in[i], exec.in_stride[i], lines, p->tail_size_in);
         } else {
             /* Reuse input pointers directly */
             const size_t loop_size = tail_blocks * exec.block_size_in;
@@ -447,8 +460,9 @@ static void op_pass_run(const SwsFrame *out, const SwsFrame 
*in, const int y,
     comp->func(&tail, comp->priv, num_blocks - tail_blocks, y, num_blocks, y + 
h);
 
     for (int i = 0; memcpy_out && i < p->planes_out; i++) {
+        const int lines = h >> tail.out_sub_y[i];
         copy_lines(exec.out[i], exec.out_stride[i],
-                   tail.out[i], tail.out_stride[i], h, p->tail_size_out);
+                   tail.out[i], tail.out_stride[i], lines, p->tail_size_out);
     }
 }
 

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

Reply via email to