From c13cfd931ddb6953cf282ab64c28941d41512620 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
Date: Wed, 13 May 2026 14:29:26 +0200
Subject: [PATCH xserver 8/9] dri2: Use booleans for (fake) front buffer
 tracking in do_get_buffers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This works as intended — the (fake) front buffer needs to be added
only if the client didn't request it in the first place — even if the
client requests the same attachment multiple times. This ensures we
never try to access more than (count + 1) entries of the buffers array.

Fixes: ff6c7764c290 ("DRI2: Implement protocol for DRI2GetBuffersWithFormat")
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
---
 hw/xfree86/dri2/dri2.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git ./hw/xfree86/dri2/dri2.c ../hw/xfree86/dri2/dri2.c
index 90ad63d6576a..7756aeedf114 100644
--- ./hw/xfree86/dri2/dri2.c
+++ ../hw/xfree86/dri2/dri2.c
@@ -558,19 +558,20 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
 static DRI2BufferPtr *
 do_get_buffers(DrawablePtr pDraw, int *width, int *height,
                unsigned int *attachments, int count, int *out_count,
                int has_format)
 {
     DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
     DRI2ScreenPtr ds;
     DRI2BufferPtr *buffers;
-    int need_real_front = 0;
-    int need_fake_front = 0;
-    int have_fake_front = 0;
+    Bool need_real_front = FALSE;
+    Bool have_real_front = FALSE;
+    Bool need_fake_front = FALSE;
+    Bool have_fake_front = FALSE;
     int front_format = 0;
     int dimensions_match;
     int buffers_changed = 0;
     int i;
 
     if (!pPriv) {
         *width = pDraw->width;
         *height = pDraw->height;
@@ -593,65 +594,63 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
 
         if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
                                      format, dimensions_match, &buffers[i]))
             buffers_changed = 1;
 
         if (buffers[i] == NULL)
             goto err_out;
 
-        /* If the drawable is a window and the front-buffer is requested,
-         * silently add the fake front-buffer to the list of requested
-         * attachments.  The counting logic in the loop accounts for the case
-         * where the client requests both the fake and real front-buffer.
+        /* In certain cases the (fake) front buffer is always needed, so return
+         * it even if the client failed to request it.
+         * The logic in & after the loop accounts for the case where the client
+         * does request the (fake) front buffer, to avoid returning it multiple
+         * times.
          */
         if (attachment == DRI2BufferBackLeft) {
-            need_real_front++;
+            need_real_front = TRUE;
             front_format = format;
         }
 
         if (attachment == DRI2BufferFrontLeft) {
-            need_real_front--;
+            have_real_front = TRUE;
             front_format = format;
 
-            if (pDraw->type == DRAWABLE_WINDOW) {
-                need_fake_front++;
-            }
+            if (pDraw->type == DRAWABLE_WINDOW)
+                need_fake_front = TRUE;
         }
 
         if (pDraw->type == DRAWABLE_WINDOW) {
-            if (attachment == DRI2BufferFakeFrontLeft) {
-                need_fake_front--;
-                have_fake_front = 1;
-            }
+            if (attachment == DRI2BufferFakeFrontLeft)
+                have_fake_front = TRUE;
         }
     }
 
-    if (need_real_front > 0) {
+    if (need_real_front && !have_real_front) {
         if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft,
                                      front_format, dimensions_match,
                                      &buffers[i]))
             buffers_changed = 1;
 
         if (buffers[i] == NULL)
             goto err_out;
         i++;
     }
 
-    if (need_fake_front > 0) {
+    if (need_fake_front && !have_fake_front) {
         if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft,
                                      front_format, dimensions_match,
                                      &buffers[i]))
             buffers_changed = 1;
 
         if (buffers[i] == NULL)
             goto err_out;
 
         i++;
-        have_fake_front = 1;
+        have_fake_front = TRUE;
     }
 
     *out_count = i;
 
     update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width,
                                  height);
 
     /* If the client is getting a fake front-buffer, pre-fill it with the
-- 
2.53.0

