ati_bpp_from_datatype() returns 0 for unrecognized dp_datatype nibble
values (0, 1, or >= 7). ati_host_data_flush() only guards against the
bpp == 24 case but not bpp == 0, leading to:

  1. Division by zero at "pix_count /= ctx.bpp" (SIGFPE) when
     src_datatype is SRC_COLOR.
  2. g_assert_not_reached() in stn_he_p() when bypp (= bpp/8 = 0)
     hits the default case of the size switch.

Both are guest-triggerable via MMIO writes to the dp_datatype register
while a HOST_DATA blit is active.

Add an explicit bpp == 0 check with LOG_GUEST_ERROR before proceeding
with the blit, consistent with the existing check in ati_2d_do_blt().

Reported-by: Feifan Qian <[email protected]>
Cc: [email protected]
Signed-off-by: Junjie Cao <[email protected]>
---
 hw/display/ati_2d.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 8ef82bb87f..22dd811bd8 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -377,6 +377,11 @@ bool ati_host_data_flush(ATIVGAState *s)
 
     setup_2d_blt_ctx(s, &ctx);
 
+    if (!ctx.bpp) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "host_data_blt: invalid bpp from datatype\n");
+        return false;
+    }
     if (ctx.bpp == 24) {
         qemu_log_mask(LOG_UNIMP,
                       "host_data_blt: unsupported in 24 bits mode\n");
-- 
2.43.0


Reply via email to