Commit a5f8d33682 for qemu.org

commit a5f8d33682be079e6b9b41f07b2eb517121b3b46
Author: Peter Maydell <peter.maydell@linaro.org>
Date:   Mon Jul 6 18:33:24 2026 +0100

    hw/display/exynos4210_fimd: Clamp windows to screen size

    In exynos4210_fimd_update(), we iterate through the enabled windows,
    blitting them to the screen. We assume here that the guest has not
    programmed the window's coordinates to be outside the overall LCD
    screen resulation, but we never check this. This can result in the
    guest being able to cause us to access outside our allocated
    framebuffer backing memory.

    Since all the coordinates here are unsigned, they can't be off
    the left/top side of the screen, only the bottom/right. If
    the top left corner of the window is out of bounds, the whole
    window is invisible and we can skip it. If the bottom right
    corner is out of bounds, we clamp it to the screen size so that
    we only draw the visible part.

    Cc: qemu-stable@nongnu.org
    Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3795
    Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
    Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
    Message-id: 20260706173324.804340-4-peter.maydell@linaro.org

diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 52f2285cf5..6c062a28c0 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1237,7 +1237,7 @@ static bool exynos4210_fimd_update(void *opaque)
     bool blend = false;
     uint8_t *host_fb_addr;
     bool is_dirty = false;
-    uint32_t global_width;
+    uint32_t global_width, global_height;
     uint32_t window_width;

     if (!s || !s->console || !s->enabled ||
@@ -1246,16 +1246,28 @@ static bool exynos4210_fimd_update(void *opaque)
     }

     global_width = exynos4210_fimd_global_width(s);
+    global_height = exynos4210_fimd_global_height(s);
     exynos4210_update_resolution(s);
     surface = qemu_console_surface(s->console);

     for (i = 0; i < NUM_OF_WINDOWS; i++) {
         w = &s->window[i];
         if ((w->wincon & FIMD_WINCON_ENWIN) && w->host_fb_addr) {
-            scrn_height = w->rightbot_y - w->lefttop_y + 1;
+            uint32_t rightbot_x, rightbot_y;
+
+            if (w->lefttop_x >= global_width ||
+                w->lefttop_y >= global_height) {
+                /* Guest has put the window entirely offscreen: ignore */
+                continue;
+            }
+
+            /* Clamp right corner coords to be within the screen */
+            rightbot_x = MIN(w->rightbot_x, global_width - 1);
+            rightbot_y = MIN(w->rightbot_y, global_height - 1);
+            scrn_height = rightbot_y - w->lefttop_y + 1;
             scrn_width = w->virtpage_width;
             /* Number of bytes to actually draw */
-            window_width = w->rightbot_x - w->lefttop_x + 1;
+            window_width = rightbot_x - w->lefttop_x + 1;
             /* Total width of virtual screen page in bytes */
             inc_size = scrn_width + w->virtpage_offsize;
             host_fb_addr = w->host_fb_addr;