From b81f9d3f94c3327b939c68f64e925927ca7e0840 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 26 Mar 2023 09:47:46 -0400 Subject: [PATCH] wayland: Comply with protocol requirements If you send a bad anchor rect to mutter, it crashes. Thats not great, so lets not do that. --- gdk/wayland/gdkpopup-wayland.c | 35 ++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/gdk/wayland/gdkpopup-wayland.c b/gdk/wayland/gdkpopup-wayland.c index a79670aef2..fd991858b5 100644 --- a/gdk/wayland/gdkpopup-wayland.c +++ b/gdk/wayland/gdkpopup-wayland.c @@ -744,6 +744,8 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup, GdkRectangle geometry; uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE; const GdkRectangle *anchor_rect; + int anchor_rect_x, anchor_rect_y; + int anchor_rect_x2, anchor_rect_y2; int real_anchor_rect_x, real_anchor_rect_y; int anchor_rect_width, anchor_rect_height; int rect_anchor_dx; @@ -772,11 +774,36 @@ create_dynamic_positioner (GdkWaylandPopup *wayland_popup, gdk_wayland_surface_get_window_geometry (surface->parent, &parent_geometry); anchor_rect = gdk_popup_layout_get_anchor_rect (layout); - real_anchor_rect_x = anchor_rect->x - parent_geometry.x; - real_anchor_rect_y = anchor_rect->y - parent_geometry.y; - anchor_rect_width = MAX (anchor_rect->width, 1); - anchor_rect_height = MAX (anchor_rect->height, 1); + /* Wayland protocol requires that the anchor rect is specified + * wrt. to the parent geometry, and that it is non-empty and + * contained in the parent geometry. + */ + anchor_rect_x = anchor_rect->x - parent_geometry.x; + anchor_rect_y = anchor_rect->y - parent_geometry.y; + anchor_rect_x2 = anchor_rect_x + anchor_rect->width; + anchor_rect_y2 = anchor_rect_y + anchor_rect->height; + + anchor_rect_x = CLAMP (anchor_rect_x, 0, parent_geometry.width - 1); + anchor_rect_y = CLAMP (anchor_rect_y, 0, parent_geometry.height - 1); + anchor_rect_x2 = CLAMP (anchor_rect_x, 0, parent_geometry.width - 1); + anchor_rect_y2 = CLAMP (anchor_rect_y, 0, parent_geometry.height - 1); + + if (anchor_rect_x2 <= anchor_rect_x || anchor_rect_y2 <= anchor_rect_y) + { + /* Somebody gave a bad anchor rect. Just make something up */ + real_anchor_rect_x = 0; + real_anchor_rect_y = 0; + anchor_rect_width = 1; + anchor_rect_height = 1; + } + else + { + real_anchor_rect_x = anchor_rect_x; + real_anchor_rect_y = anchor_rect_y; + anchor_rect_width = anchor_rect_x2 - anchor_rect_x; + anchor_rect_height = anchor_rect_y2 - anchor_rect_y; + } gdk_popup_layout_get_offset (layout, &rect_anchor_dx, &rect_anchor_dy);