From c55d42c1691dd24ddeb8b7c3ff65f006a25ef300 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sun, 24 May 2026 10:01:18 +0200 Subject: [PATCH] wayland: guard wl_menu_paint_entry against unrealized menus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ASan caught a heap-buffer-overflow at wl_menu_paint_entry:8675 writing 4 bytes BEFORE a pixman-allocated 40-byte region. The bottom-bevel loop wrote dst[(y + h - 1) * stride + col] where y=0, h=0 (because menu->entry_height was still 0 from before wMenuRealize), stride=1 (initial 1×10 buffer), col=0 → offset -1 → write -4 bytes from start of the pixman bits buffer. Trigger: updateOptionsMenu (right-click on titlebar) calls wMenuSetEnabled which paints both the menu and its brother unconditionally. The brother had not been realized yet on first right-click, so menu->entry_height was 0. This was the corruption that caused the later 'double free' on pixman_image_unref of unrelated frame buffers (heap was already trashed by this OOB write). Fix: bail early in wl_menu_paint_entry if entry_height is zero or if fb is still at the 1×10 placeholder size — paint will fire again correctly after wMenuRealize. --- src/backend/wayland/wl_backend.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 40af34e..93da985 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -8606,6 +8606,14 @@ static void wl_menu_paint_entry(WMenu *menu, int index, int selected) if (!fb || !fb->image) return; + /* Guard against painting before wMenuRealize: entry_height is 0, + * fb->image is the initial 1x10 placeholder, and the bevel-line + * computations below would write outside the pixman buffer. + * wMenuSetEnabled() in particular triggers paints on the brother + * during updateOptionsMenu before the menu is realized. */ + if (menu->entry_height <= 0 || fb->width <= 1 || fb->height <= 10) + return; + WScreen *scr = menu->frame->screen_ptr; WMenuEntry *entry = menu->entries[index]; int y = menu->entry_height * index;