From fdd4e83ea06e426558ded06f6b8d6ed9f752da21 Mon Sep 17 00:00:00 2001 From: Prasanna Dabi 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 8e17f258f0..0ddfafb1b8 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); }