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]
