From f2e49a8b672613c34de8dad0ae51ad83d360fc79 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sun, 24 May 2026 08:25:14 +0200 Subject: [PATCH] menu: fix infinite recursion in findMenuWalk via brother A WMenu's brother is a parallel copy of the same menu used when the menu is torn off / buttoned. The brother shares cascade pointers that reference back into the original tree, so recursing into both m->brother and m->cascades[i] cycled (brother->cascades[i] == m's own cascade entry, which has its own brother, etc.) and overflowed the stack on any cascaded menu. Inline the brother hit-test instead of recursing into it. Cascades themselves are walked recursively as before so sub-sub-menus remain reachable. --- src/menu.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/menu.c b/src/menu.c index 293c3d6..09ccc93 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1113,6 +1113,11 @@ static void selectEntry(WMenu * menu, int entry_no) * the pointer is over the entries area. Updates *deepest_p to the * deepest mapped menu under (x,y) so that sub-sub-menus (cascade-of- * cascade-...) are reachable. + * + * Brother menus are checked but NOT recursed into — a brother's + * cascade pointers reference back into the original tree and would + * cycle (brother->cascades[i] is the same WMenu as menu->cascades[i], + * which has its own brother, etc.). */ static void findMenuWalk(WMenu *m, int x, int y, WMenu **deepest_p, int *dx_p, int *dy_p) @@ -1125,8 +1130,13 @@ static void findMenuWalk(WMenu *m, int x, int y, *dx_p = x - m->frame_x; *dy_p = y - m->frame_y - m->frame->top_width; } - if (m->brother) - findMenuWalk(m->brother, x, y, deepest_p, dx_p, dy_p); + if (m->brother && m->brother->flags.mapped && + x >= m->brother->frame_x && x < m->brother->frame_x + MENUW(m->brother) && + y >= m->brother->frame_y && y < m->brother->frame_y + MENUH(m->brother)) { + *deepest_p = m->brother; + *dx_p = x - m->brother->frame_x; + *dy_p = y - m->brother->frame_y - m->brother->frame->top_width; + } for (int i = 0; i < m->cascade_no; i++) findMenuWalk(m->cascades[i], x, y, deepest_p, dx_p, dy_p); }