[FFmpeg-devel] [PATCH] swscale/yuv2rgb: fix out-of-bounds access with odd srcSliceH in YUV422 (PR #20883)

2025-11-10 Thread thomasdullien via ffmpeg-devel
PR #20883 opened by thomasdullien
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20883
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20883.patch

For transparency: I am experimenting with an AI-assisted patch process, where 
the AI agent attempts to help
root-cause analyze a crash by means of reproducing the crash with ASAN, making 
a recording with 'rr', and
documenting the analysis at a granular level with verbatim quotes from the 'rr' 
trace. This root-cause analysis
is then iteratively reviewed (e.g. as a human reviewer I check it for accuracy 
and plausibility) before a patch is
generated. The process generates a detailed analysis report, an 'rr' trace that 
can be shared with other to help
with the verification, and a patch. Given that it is unlear how to best share 
the 'rr' trace, I have only attached the
detailed root-cause analysis document that was at the end of the iterative 
process.

Tests have been run and pass.

=== Description ===

The YUV422 conversion functions process 2 rows at once but did not
check whether a second row actually exists when srcSliceH is odd.
With bottom-to-top processing (negative strides), this caused
pu_2/pv_2 pointers to be set before the buffer start, leading to
out-of-bounds memory access when accessing pu_2[0] or pv_2[0].

This patch adds a check to skip row 2 processing in the final
remainder section when srcSliceH is odd, preventing access to
non-existent rows while still processing all available source lines.

Performance impact is minimal: one bitwise AND operation only in the
remainder section (when width is not divisible by 4), so performance
regression is unlikely to be severe.

Fixes: https://trac.ffmpeg.org/ticket/11691

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude 


From 95b96efa7bc7b587e857b3e780d72b1192cb6a49 Mon Sep 17 00:00:00 2001
From: Thomas Dullien 
Date: Sun, 9 Nov 2025 12:16:27 +0100
Subject: [PATCH] swscale/yuv2rgb: fix out-of-bounds access with odd srcSliceH
 in YUV422
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The YUV422 conversion functions process 2 rows at once but did not
check whether a second row actually exists when srcSliceH is odd.
With bottom-to-top processing (negative strides), this caused
pu_2/pv_2 pointers to be set before the buffer start, leading to
out-of-bounds memory access when accessing pu_2[0] or pv_2[0].

This patch adds a check to skip row 2 processing in the final
remainder section when srcSliceH is odd, preventing access to
non-existent rows while still processing all available source lines.

Performance impact is minimal: one bitwise AND operation only in the
remainder section (when width is not divisible by 4), so performance
regression is unlikely to be severe.

Fixes: https://trac.ffmpeg.org/ticket/11691

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude 
---
 libswscale/yuv2rgb.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c
index 48089760f5..cb5bcfaac2 100644
--- a/libswscale/yuv2rgb.c
+++ b/libswscale/yuv2rgb.c
@@ -364,8 +364,10 @@ const int *sws_getCoefficients(int colorspace)
 LOADCHROMA(1, 0);   \
 PUTFUNC(1, 0, 0);   \
 \
-LOADCHROMA(2, 0);   \
-PUTFUNC(2, 0, 0 + 8);   \
+if (!(srcSliceH & 1)) { \
+LOADCHROMA(2, 0);   \
+PUTFUNC(2, 0, 0 + 8);   \
+}   \
 ENDYUV2RGBFUNC()
 
 #define LOADDITHER16\
-- 
2.49.1

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


[FFmpeg-devel] [PATCH] Bug fix attempt for #11691 - swscale: Fix heap-buffer-overflow in unscaled YUV-to-RGB conversion (PR #20864)

2025-11-08 Thread thomasdullien via ffmpeg-devel
PR #20864 opened by thomasdullien
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20864
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20864.patch

For transparency: I am experimenting with an AI-assisted patch process, where 
the AI agent attempts to help
root-cause analyze a crash by means of reproducing the crash with ASAN, making 
a recording with 'rr', and
documenting the analysis at a granular level with verbatim quotes from the 'rr' 
trace. This root-cause analysis
is then iteratively reviewed (e.g. as a human reviewer I check it for accuracy 
and plausibility) before a patch is
generated. The process generates a detailed analysis report, an 'rr' trace that 
can be shared with other to help
with the verification, and a patch. Given that it is unlear how to best share 
the 'rr' trace, I have only attached the
detailed root-cause analysis document.

This patch attempts to address https://trac.ffmpeg.org/ticket/11691

It should be noted that I am very much not an expert in the ffmpeg codebase, so 
please bear with me if the proposed
patch isn't what is needed. I've re-run the test suite, and it looks very 
plausible to me.

- Description -

Many YUV-to-RGB conversion functions in yuv2rgb.c process 2 scanlines
per iteration. When sws_scale() is called with insufficient source rows
available (e.g., srcSliceY=1 with only 2 total rows, leaving 1 row),
these functions would read beyond the allocated buffer bounds.

This occurred because the convert_unscaled path did not verify that at
least 2 rows were available before calling the conversion function. The
issue was particularly evident with formats like yuv422p when converting
to rgb4 or similar pixel formats.

Add bounds checking in scale_internal() before invoking convert_unscaled
to ensure at least 2 source rows remain after accounting for the slice
offset. If fewer than 2 rows are available, return 0 (no rows processed)
instead of attempting conversion, preventing the out-of-bounds access.

Fixes: https://trac.ffmpeg.org/ticket/11691

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude 
---




From 6138573dd0364eee7051eaa1ba27cebee738bb5a Mon Sep 17 00:00:00 2001
From: "Thomas Dullien (AI assisted)" 
Date: Sat, 8 Nov 2025 14:30:28 +0100
Subject: [PATCH] swscale: Fix heap-buffer-overflow in unscaled YUV-to-RGB
 conversion
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Many YUV-to-RGB conversion functions in yuv2rgb.c process 2 scanlines
per iteration. When sws_scale() is called with insufficient source rows
available (e.g., srcSliceY=1 with only 2 total rows, leaving 1 row),
these functions would read beyond the allocated buffer bounds.

This occurred because the convert_unscaled path did not verify that at
least 2 rows were available before calling the conversion function. The
issue was particularly evident with formats like yuv422p when converting
to rgb4 or similar pixel formats.

Add bounds checking in scale_internal() before invoking convert_unscaled
to ensure at least 2 source rows remain after accounting for the slice
offset. If fewer than 2 rows are available, return 0 (no rows processed)
instead of attempting conversion, preventing the out-of-bounds access.

Fixes: https://trac.ffmpeg.org/ticket/11691

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude 
---
 libswscale/swscale.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index f4c7eccac4..7086b0f0e2 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -1140,6 +1140,23 @@ static int scale_internal(SwsContext *sws,
 int offset  = srcSliceY_internal;
 int slice_h = srcSliceH;
 
+/* Many YUV-to-RGB conversion functions process 2 scanlines per 
iteration
+ * and require at least 2 rows to be available in the source buffer.
+ * Check if we have sufficient rows after considering the offset. */
+int src_rows_remaining = sws->src_h - offset;
+if (slice_h > src_rows_remaining) {
+/* Clamp to available rows */
+slice_h = src_rows_remaining;
+}
+if (slice_h < 2) {
+/* Cannot safely process: conversion functions that process 2 rows
+ * per iteration would read beyond buffer bounds. Return 0 to 
indicate
+ * no rows were processed. This is a safety check to prevent
+ * heap-buffer-overflow in yuv2rgb.c and similar conversion 
functions. */
+ret = 0;
+goto unscaled_end;
+}
+
 // for dst slice scaling, offset the pointers to match the unscaled API
 if (scale_dst) {
 av_assert0(offset == 0);
@@ -1160,6 +1177,7 @@ static int scale_internal(SwsContext *sws,
 
 ret = c->convert_unscaled(c, src2, srcStride2, offset, slice_h,