Commit f93d46898b for ffmpeg

commit f93d46898b6a939fcc4d6a147b3c5aede82a2383
Author: Michael Niedermayer <michael@niedermayer.cc>
Date:   Sat Nov 7 22:08:08 2026 +0100

    swscale: reject interlaced frames whose bottom field lacks a chroma row

    Fixes: heap-buffer-overflow (read and write)
    Fixes: 5TZcJN8RG7oW

    Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24851

    Out of array read and write Replicated through API with ASAN

diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index a7715a79a9..90a9a40d78 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -1535,6 +1535,12 @@ static int validate_params(SwsContext *ctx)
     return 0;
 }

+static int bottom_field_fits(const AVFrame *frame, const SwsFormat *field)
+{
+    const int vsub = field->desc->log2_chroma_h;
+    return 2 * AV_CEIL_RSHIFT(field->height, vsub) <= AV_CEIL_RSHIFT(frame->height, vsub);
+}
+
 int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src)
 {
     SwsInternal *s = sws_internal(ctx);
@@ -1606,6 +1612,13 @@ int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src)
             goto fail;
         }

+        if (field == FIELD_BOTTOM &&
+            (!bottom_field_fits(src, &src_fmt) || !bottom_field_fits(dst, &dst_fmt))) {
+            err_msg = "The bottom field has fewer chroma rows than its height requires";
+            ret = AVERROR(EINVAL);
+            goto fail;
+        }
+
         src_ok = ff_test_fmt(backends, &src_fmt, 0);
         dst_ok = ff_test_fmt(backends, &dst_fmt, 1);
         if ((!src_ok || !dst_ok) && !ff_fmt_equal(&src_fmt, &dst_fmt)) {