From e07743373aa1c6871bf6ef33e21f989194867150 Mon Sep 17 00:00:00 2001 From: guping Date: Fri, 1 Aug 2025 06:29:08 +0000 Subject: [PATCH] hw/display/qxl-render: fix qxl_unpack_chunks() chunk size calculation cherry-pick from 8e8cb3b5722babe7e7b597b3805bf09f24ed6979 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of multiple chunks, code in qxl_unpack_chunks() takes size of the wrong (next in the chain) chunk, instead of using current chunk size. This leads to wrong number of bytes being copied, and to crashes if next chunk size is larger than the current one. Based on the code by Gao Yong. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1628 Tested-by: Thaddeus Hogan Tested-by: Vadim Zeitlin Signed-off-by: Michael Tokarev Reviewed-by: Thomas Huth Message-ID: <20250221134856.478806-1-mjt@tls.msk.ru> Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: guping --- hw/display/qxl-render.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index ec99ec887a..7df961fcdb 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -222,6 +222,7 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, uint32_t max_chunks = 32; size_t offset = 0; size_t bytes; + QXLPHYSICAL next_chunk_phys = 0; for (;;) { bytes = MIN(size - offset, chunk->data_size); @@ -230,7 +231,15 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, if (offset == size) { return; } - chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id, + next_chunk_phys = chunk->next_chunk; + /* fist time, only get the next chunk's data size */ + chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id, + sizeof(QXLDataChunk)); + if (!chunk) { + return; + } + /* second time, check data size and get data */ + chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id, sizeof(QXLDataChunk) + chunk->data_size); if (!chunk) { return; -- Gitee