From a37bf79cefea0f8ea868c3d803ca0733e8d45859 Mon Sep 17 00:00:00 2001 From: Arkadiusz Miszczyszyn Date: Thu, 10 Sep 2026 10:26:08 +0200 Subject: [PATCH] core: Do not abort on overflowing window positions in edge resistance A native Wayland Chrome window restored maximized can end up with a frame rect x near INT_MAX. Computing resistance edges then overflows BOX_RIGHT, split_edge's assertion fails and cinnamon aborts, killing every client. Skip windows whose frame rect is outside a sane range and keep an edge unsplit instead of asserting. Co-Authored-By: Claude Opus 5 (1M context) --- src/core/boxes.c | 19 +++++++++++++++++-- src/core/edge-resistance.c | 25 +++++++++++++++++++------ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/core/boxes.c b/src/core/boxes.c index c5e94f7a6..db869fac8 100644 --- a/src/core/boxes.c +++ b/src/core/boxes.c @@ -1635,6 +1635,19 @@ add_edges (GList *cur_edges, /* Remove any part of old_edge that intersects remove and add any resulting * edges to cur_list. Return cur_list when finished. */ +static GList * +keep_unsplit_edge (GList *cur_list, + const MetaEdge *old_edge) +{ + MetaEdge *copy; + + g_warning_once ("split_edge: edge and removal rectangle do not overlap, keeping the edge unsplit"); + + copy = g_new (MetaEdge, 1); + *copy = *old_edge; + return g_list_prepend (cur_list, copy); +} + static GList* split_edge (GList *cur_list, const MetaEdge *old_edge, @@ -1645,7 +1658,8 @@ split_edge (GList *cur_list, { case META_SIDE_LEFT: case META_SIDE_RIGHT: - g_assert (meta_rectangle_vert_overlap (&old_edge->rect, &remove->rect)); + if (!meta_rectangle_vert_overlap (&old_edge->rect, &remove->rect)) + return keep_unsplit_edge (cur_list, old_edge); if (BOX_TOP (old_edge->rect) < BOX_TOP (remove->rect)) { temp_edge = g_new (MetaEdge, 1); @@ -1666,7 +1680,8 @@ split_edge (GList *cur_list, break; case META_SIDE_TOP: case META_SIDE_BOTTOM: - g_assert (meta_rectangle_horiz_overlap (&old_edge->rect, &remove->rect)); + if (!meta_rectangle_horiz_overlap (&old_edge->rect, &remove->rect)) + return keep_unsplit_edge (cur_list, old_edge); if (BOX_LEFT (old_edge->rect) < BOX_LEFT (remove->rect)) { temp_edge = g_new (MetaEdge, 1); diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c index fc7c06602..000664fa4 100644 --- a/src/core/edge-resistance.c +++ b/src/core/edge-resistance.c @@ -28,15 +28,28 @@ #include "core/meta-workspace-manager-private.h" #include "core/workspace-private.h" +static gboolean +frame_rect_in_sane_range (MetaWindow *window) +{ + MetaRectangle rect; + + meta_window_get_frame_rect (window, &rect); + + return rect.width >= 0 && rect.height >= 0 && + ABS ((gint64) rect.x) + rect.width <= G_MAXINT / 2 && + ABS ((gint64) rect.y) + rect.height <= G_MAXINT / 2; +} + /* A simple macro for whether a given window's edges are potentially * relevant for resistance/snapping during a move/resize operation */ -#define WINDOW_EDGES_RELEVANT(window, display) \ - meta_window_should_be_showing (window) && \ - window != display->grab_window && \ - window->type != META_WINDOW_DESKTOP && \ - window->type != META_WINDOW_MENU && \ - window->type != META_WINDOW_SPLASHSCREEN +#define WINDOW_EDGES_RELEVANT(window, display) \ + meta_window_should_be_showing (window) && \ + window != display->grab_window && \ + window->type != META_WINDOW_DESKTOP && \ + window->type != META_WINDOW_MENU && \ + window->type != META_WINDOW_SPLASHSCREEN && \ + frame_rect_in_sane_range (window) struct ResistanceDataForAnEdge {