xwayland: Avoid NULL pointer dereference in damage_report()

Commit 34934c37d6 restored calling register_damage() in
xwl_realize_window() before ensure_surface_for_window().

However if register_damage() succeeds and ensure_surface_for_window()
returns NULL, it would exit without "unregistering" the damage hook.

The X11 window, however, may still get damages reports, in which case
xwl_window_from_window() would return NULL, causing a NULL pointer
dereference in damage_report().

To avoid the issue, make sure we unregister the damage report if
ensure_surface_for_window() has failed, and add an early exit in
damage_report() if xwl_window is NULL.

v2: unregister_damage() unconditionally if ensure_surface_for_window()
    failed (Michel Dänzer)

Fixes: commit 34934c37d6 ("revert: register damage before ensure_surface_for_window")
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/work_items/1886
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2190>
This commit is contained in:
Olivier Fourdan 2026-04-22 19:04:13 +02:00 committed by Marge Bot
parent 6c838f7cb8
commit 36f53145e4

View file

@ -301,8 +301,10 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
PixmapPtr window_pixmap;
if (xwl_window &&
xwl_window->surface_window_damage &&
if (!xwl_window)
return;
if (xwl_window->surface_window_damage &&
RegionNotEmpty(pRegion)) {
if (!RegionNotEmpty(xwl_window->surface_window_damage))
need_source_validate_inc(xwl_screen);
@ -315,7 +317,7 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
if (xwl_screen->ignore_damage)
return;
if (xwl_window && xorg_list_is_empty(&xwl_window->link_damage))
if (xorg_list_is_empty(&xwl_window->link_damage))
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
window_pixmap = screen->GetWindowPixmap(xwl_window->surface_window);
@ -1638,8 +1640,10 @@ xwl_realize_window(WindowPtr window)
}
xwl_window = ensure_surface_for_window(window);
if (!xwl_window)
if (!xwl_window) {
unregister_damage(window);
return FALSE;
}
return TRUE;
}