wayland: guard wl_menu_paint_entry against unrealized menus

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.
This commit is contained in:
Window Maker 2026-05-24 10:01:18 +02:00
parent d6e10203fa
commit c55d42c169
1 changed files with 8 additions and 0 deletions

View File

@ -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;