aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tokarev <mjt@tls.msk.ru>2025-02-21 16:34:52 +0300
committerMichael Tokarev <mjt@tls.msk.ru>2025-07-25 09:42:11 +0300
commitb8882becd572d3afb888c836a6ffc7f92c17d1c5 (patch)
tree2cbe2f1931ac5422bdebfefbedbcec210c03ef6e
parent9e601684dc24a521bb1d23215a63e5c6e79ea0bb (diff)
downloadqemu-b8882becd572d3afb888c836a6ffc7f92c17d1c5.zip
qemu-b8882becd572d3afb888c836a6ffc7f92c17d1c5.tar.gz
qemu-b8882becd572d3afb888c836a6ffc7f92c17d1c5.tar.bz2
hw/display/qxl-render.c: fix qxl_unpack_chunks() chunk size calculation
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 Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> Reviewed-by: Thomas Huth <thuth@redhat.com>
-rw-r--r--hw/display/qxl-render.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index eda6d3d..c6a9ac1 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;