Package: xfwm4
Version: 4.18.0-1
Severity: normal
Tags: patch upstream

Dear maintainer,

xfwm4 crashes on switching between windows (ALT+TAB).

The workaround is to set the "Cycle through windows in a list" option in "Window
Manager Tweaks", this will use a different ALT+TAB windows view.


kernel log message:

  traps: xfwm4[1961] trap divide error ip:5616f7acfda1 sp:7ffe3769abb0 error:0 
in xfwm4[5616f7a97000+3f000]


I have collected the coredump and the stack trace points createWindowlist
function, at ./src/tabwin.c:558:

  Program terminated with signal SIGFPE, Arithmetic exception.
  [...]
  (gdb) where
  #0  0x0000561b6bfd3da1 in createWindowlist (tabwin_widget=0x561b7319a270, 
screen_info=0x561b72fdfa00) at ./src/tabwin.c:558
  #1  tabwinCreateWidget (monitor_num=<optimized out>, 
screen_info=0x561b72fdfa00, tabwin=0x561b72fac000) at ./src/tabwin.c:835
  #2  tabwinCreate (client_list=client_list@entry=0x7ffd60ada298, 
selected=selected@entry=0x561b72eddce0, display_workspace=<optimized out>) at 
./src/tabwin.c:941
  #3  0x0000561b6bfadebd in clientCycle (c=<optimized out>, 
event=0x561b73234e40) at ./src/cycle.c:533
  #4  0x0000561b6bfb210b in handleKeyPress (event=0x561b73234e40, 
display_info=0x561b72de9970) at ./src/events.c:329
  #5  handleEvent (event=<optimized out>, display_info=0x561b72de9970) at 
./src/events.c:2181
  #6  xfwm4_event_filter (event=0x561b73234e40, data=0x561b72de9970) at 
./src/events.c:2302
  #7  0x0000561b6bfafd80 in eventXfwmFilter (gdk_xevent=<optimized out>, 
gevent=<optimized out>, data=<optimized out>) at ./src/event_filter.c:175
  #8  0x00007f70b67846ff in ?? () from /lib/x86_64-linux-gnu/libgdk-3.so.0
  #9  0x00007f70b6784a54 in ?? () from /lib/x86_64-linux-gnu/libgdk-3.so.0
  #10 0x00007f70b67263b0 in gdk_display_get_event () from 
/lib/x86_64-linux-gnu/libgdk-3.so.0
  #11 0x00007f70b6784792 in ?? () from /lib/x86_64-linux-gnu/libgdk-3.so.0
  #12 0x00007f70b5b7b7a9 in g_main_context_dispatch () from 
/lib/x86_64-linux-gnu/libglib-2.0.so.0
  #13 0x00007f70b5b7ba38 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  #14 0x00007f70b5b7bcef in g_main_loop_run () from 
/lib/x86_64-linux-gnu/libglib-2.0.so.0
  #15 0x00007f70b6008495 in gtk_main () from /lib/x86_64-linux-gnu/libgtk-3.so.0
  #16 0x0000561b6bf9db3d in main (argc=<optimized out>, argv=<optimized out>) 
at ./src/main.c:764


Related part of code:

  xfwm4-4.18.0/src/tabwin.c
  556         if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
  557         {
  558             gtk_grid_attach (GTK_GRID (windowlist), GTK_WIDGET 
(window_button),
  559                              packpos % tabwin->grid_cols, packpos / 
tabwin->grid_cols,
  560                              1, 1);
  561         }


Based on the collected coredump, the value of tabwin->grid_cols is 0,
which causes a division by zero in line 559:

  (gdb) print tabwin->grid_cols
  $1 = 0


The tabwin->grid_cols is set in the function computeTabwinData, which is called
from tabwinCreateWidget:

  xfwm4-4.18.0/src/tabwin.c
  757 static TabwinWidget *
  758 tabwinCreateWidget (Tabwin *tabwin, ScreenInfo *screen_info, gint 
monitor_num)
  759 {
  [...]
  798     if (tabwin->icon_list == NULL)
  799     {
  800         computeTabwinData (screen_info, tabwin_widget);
  801     }


The value is calculated based on tabwin->monitor_width and size_request:

  xfwm4-4.18.0/src/tabwin.c
  639 static void
  640 computeTabwinData (ScreenInfo *screen_info, TabwinWidget *tabwin_widget)
  641 {
  [...]
  655     tabwin->monitor_width = getMinMonitorWidth (screen_info);
  [...]
  684         size_request = tabwin->icon_size + tabwin->label_height + 2 * 
WIN_ICON_BORDER;
  685         tabwin->grid_cols = (int) (floor ((double) tabwin->monitor_width 
* WIN_MAX_RATIO /
  686                                           (double) size_request));


The values of the related variables are:

  (gdb) print tabwin->icon_size
  $2 = 288
  (gdb) print tabwin->label_height
  $3 = 19
  (gdb) print size_request
  $4 = 317
  (gdb) print tabwin->monitor_width
  $5 = 103


Checking the calculations with sample app:

   1 #include <stdio.h>
   2 #include <math.h>
   3
   4 #define WIN_ICON_BORDER 5
   5 #define WIN_MAX_RATIO 0.8
   6
   7 int
   8 main() {
   9     int icon_size = 288,
  10         label_height = 19,
  11         monitor_width = 103;
  12
  13     int size_request = icon_size + label_height + 2 * WIN_ICON_BORDER;
  14     double numerator = (double) monitor_width * WIN_MAX_RATIO;
  15
  16     printf("size_request=%d\n", size_request);
  17     printf("numerator=%lf\n", numerator);
  18
  19     double divided = numerator / size_request;
  20     double divided_after_floor = floor(divided);
  21
  22     printf("divided=%lf\n", divided);
  23     printf("divided_after_floor=%lf\n", divided_after_floor);
  24     printf("final result=%d\n", (int)divided_after_floor);
  25
  26     return 0;
  27 }


Console output:

  size_request=317
  numerator=82.400000
  divided=0.259937
  divided_after_floor=0.000000
  final result=0


The monitor_width value taken from GDK functions looks suspicious; thus, it may
require further investigation under separate bug report.

I believe the root cause of the issue is not in the xfwm4 itself, but in my
opinion xfwm4 should avoid division by zero appropriately. The crash can
be prevented by setting tabwin->grid_cols to the maximum of 1 and the calculated
value:

--- a/src/tabwin.c   2022-11-01 09:53:34.000000000 +0000
+++ b/src/tabwin.c   2025-05-30 22:37:03.668696034 +0000
@@ -682,8 +682,8 @@
             tabwin->icon_size = standard_icon_size;
         }
         size_request = tabwin->icon_size + tabwin->label_height + 2 * 
WIN_ICON_BORDER;
-        tabwin->grid_cols = (int) (floor ((double) tabwin->monitor_width * 
WIN_MAX_RATIO /
-                                          (double) size_request));
+        tabwin->grid_cols = (int) fmax(1, floor ((double) 
tabwin->monitor_width * WIN_MAX_RATIO /
+                                                 (double) size_request));
         tabwin->grid_rows = (int) (ceil ((double) tabwin->client_count /
                                          (double) tabwin->grid_cols));

@@ -702,8 +702,8 @@
             size_request = tabwin->icon_size + tabwin->label_height + 2 * 
WIN_ICON_BORDER;

             /* Recalculate with new icon size */
-            tabwin->grid_cols = (int) (floor ((double) tabwin->monitor_width * 
WIN_MAX_RATIO /
-                                              (double) size_request));
+            tabwin->grid_cols = (int) fmax(1, floor ((double) 
tabwin->monitor_width * WIN_MAX_RATIO /
+                                                     (double) size_request));
             tabwin->grid_rows = (int) (ceil ((double) tabwin->client_count /
                                              (double) tabwin->grid_cols));

@@ -720,8 +720,8 @@
         tabwin->icon_size = LISTVIEW_WIN_ICON_SIZE;
         gtk_widget_style_get (GTK_WIDGET (tabwin_widget),
                               "listview-icon-size", &tabwin->icon_size, NULL);
-        tabwin->grid_rows = (int) (floor ((double) tabwin->monitor_height * 
WIN_MAX_RATIO /
-                                          (double) (tabwin->icon_size + 2 * 
WIN_ICON_BORDER)));
+        tabwin->grid_rows = (int) fmax(1, floor ((double) 
tabwin->monitor_height * WIN_MAX_RATIO /
+                                                 (double) (tabwin->icon_size + 
2 * WIN_ICON_BORDER)));
         tabwin->grid_cols = (int) (ceil ((double) tabwin->client_count /
                                          (double) tabwin->grid_rows));
     }


Bug also exist in xfwm4_4.20.0 from Trixie, the same patch applies.

Best regards,
Adam.


-- System Information:
Debian Release: 12.11
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 
'stable-debug'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 6.1.0-37-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=pl_PL.UTF-8, LC_CTYPE=pl_PL.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages xfwm4 depends on:
ii  libc6                     2.36-9+deb12u10
ii  libcairo2                 1.16.0-7
ii  libepoxy0                 1.5.10-1
ii  libgdk-pixbuf-2.0-0       2.42.10+dfsg-1+deb12u1
ii  libglib2.0-0              2.74.6-2+deb12u6
ii  libgtk-3-0                3.24.38-2~deb12u3
ii  libpango-1.0-0            1.50.12+ds-1
ii  libpangocairo-1.0-0       1.50.12+ds-1
ii  libstartup-notification0  0.12-6+b1
ii  libwnck-3-0               43.0-3
ii  libx11-6                  2:1.8.4-2+deb12u2
ii  libxcomposite1            1:0.4.5-1
ii  libxdamage1               1:1.1.6-1
ii  libxext6                  2:1.3.4-1+b1
ii  libxfce4ui-2-0            4.18.2-2
ii  libxfce4util7             4.18.1-2
ii  libxfconf-0-3             4.18.0-2
ii  libxfixes3                1:6.0.0-2
ii  libxinerama1              2:1.1.4-3
ii  libxpresent1              1.0.0-2+b10
ii  libxrandr2                2:1.5.2-2+b1
ii  libxrender1               1:0.9.10-1.1
ii  libxres1                  2:1.2.1-1

Versions of packages xfwm4 recommends:
ii  librsvg2-common  2.54.7+dfsg-1~deb12u1

Versions of packages xfwm4 suggests:
ii  xfce4  4.18

-- no debconf information


Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to