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

`copy_buffer_data()` copied `FFABS(linesize)` bytes per row between the 
software frame and the staging buffer. The last row of a plane does not have to 
extend to the full linesize, so this reads past the end of the software frame 
on upload and writes past it on download. Same issue as fixed for 
hwcontext_cuda in f07f02abb864.

The staging path is always used for frames with a negative linesize, and by 
default for multi-plane formats (NV12, P010, ...) on the NVIDIA proprietary 
driver, where host image copies are disabled and `avoid_host_import` is on.

Reproduced through the API (`av_hwframe_transfer_data()`) with ASan on Mesa 
lavapipe, using a GRAY8 100x16 frame with linesize 128 whose last row holds 
only the visible 100 bytes:
- upload: heap-buffer-overflow READ of size 128, 0 bytes after the 2020-byte 
frame buffer (copy_buffer_data)
- download: heap-buffer-overflow WRITE of size 128, 0 bytes after the 2020-byte 
frame buffer (copy_buffer_data)

With the patch both are clean, fully padded frames are unaffected, and an 
upload/download round trip through the staging path reproduces all visible 
bytes.


>From fdd4e83ea06e426558ded06f6b8d6ed9f752da21 Mon Sep 17 00:00:00 2001
From: Prasanna Dabi <[email protected]>
Date: Tue, 20 Oct 2026 07:49:28 +0000
Subject: [PATCH] avutil/hwcontext_vulkan: copy only the bytes of the visible
 rows

copy_buffer_data() copied FFABS(linesize) bytes per row between the
software frame and the staging buffer. The last row of a plane does not
have to extend to the full linesize, so this read past the end of the
software frame on upload and wrote past it on download.

The staging path is always taken for frames with a negative linesize,
and by default for multi-plane formats on the NVIDIA proprietary driver,
where host image copies are disabled and host memory import is avoided.

Same issue as fixed for hwcontext_cuda in f07f02abb864.

Out of array read and write replicated through the API with ASAN.
---
 libavutil/hwcontext_vulkan.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 8e17f258f01..0ddfafb1b8e 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -4725,6 +4725,15 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
FFVkBuffer *vkbuf,
 {
     int err;
     VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    int bytewidth[AV_NUM_DATA_POINTERS];
+
+    /* Copy only the visible bytes of each row, the last row of a plane
+     * does not have to extend to the full linesize. */
+    for (int i = 0; i < planes; i++) {
+        bytewidth[i] = av_image_get_linesize(swf->format, swf->width, i);
+        if (bytewidth[i] < 0)
+            return bytewidth[i];
+    }
 
     if (upload) {
         for (int i = 0; i < planes; i++)
@@ -4732,7 +4741,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
FFVkBuffer *vkbuf,
                                 region[i].bufferRowLength,
                                 swf->data[i],
                                 swf->linesize[i],
-                                FFABS(swf->linesize[i]),
+                                bytewidth[i],
                                 region[i].imageExtent.height);
 
         err = ff_vk_flush_buffer(&p->vkctx, vkbuf, 0, VK_WHOLE_SIZE, 1);
@@ -4754,7 +4763,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
FFVkBuffer *vkbuf,
                                 swf->linesize[i],
                                 vkbuf->mapped_mem + region[i].bufferOffset,
                                 region[i].bufferRowLength,
-                                FFABS(swf->linesize[i]),
+                                bytewidth[i],
                                 region[i].imageExtent.height);
     }
 
-- 
2.54.0

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

Reply via email to