From: Junjie Cao <[email protected]>

ati_host_data_flush() resets host_data.next only on its success path.
When it returns early (unsupported bpp, direction, src_source, or
src_datatype), next remains stale at >= 4. The next HOST_DATA write
then stores a guest-controlled dword at acc[4+], overflowing the
4-element accumulator array.

Fix this by resetting next unconditionally in the write handler after
calling ati_host_data_flush() or ati_host_data_finish(), and removing
the reset from inside ati_host_data_flush(). This ensures the write
handler owns the full lifecycle of the accumulator index regardless of
flush success or failure.

Cc: [email protected]
Reported-by: Feifan Qian <[email protected]>
Resolves: 
https://lore.kernel.org/qemu-devel/Czyl6yVfL6sHl_o1kRk8N_LpwXMMRVhO9vgz1qCVJFagn9D4nHSKuiux39iOLty0Q3acxQq_FeovPhTQvSKus2htwjI9lTajLZmqovr0Wxs=@proton.me/
Signed-off-by: Junjie Cao <[email protected]>
Reviewed-by: Chad Jablonski <[email protected]>
Message-ID: <[email protected]>
Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
(cherry picked from commit 3565faa0ace1f258789aafaf440ab55c3419df60)
Signed-off-by: Michael Tokarev <[email protected]>

diff --git a/hw/display/ati.c b/hw/display/ati.c
index 0489995d00b..7d4e40a142c 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -1032,8 +1032,10 @@ static void ati_mm_write(void *opaque, hwaddr addr,
         s->host_data.acc[s->host_data.next++] = data;
         if (addr == HOST_DATA_LAST) {
             ati_host_data_finish(s);
+            s->host_data.next = 0;
         } else if (s->host_data.next >= 4) {
             ati_host_data_flush(s);
+            s->host_data.next = 0;
         }
         break;
     default:
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 48498677c7e..8ef82bb87fd 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -452,7 +452,6 @@ bool ati_host_data_flush(ATIVGAState *s)
     }
 
     /* Track state of the overall blit for use by the next flush */
-    s->host_data.next = 0;
     s->host_data.row = row;
     s->host_data.col = col;
     if (s->host_data.row >= ctx.dst.height) {
-- 
2.47.3


Reply via email to