Package: libqt5gui5
Version: 5.15.4+dfsg-5
Severity: important

Dear Maintainer,

When running some Qt-based applications, I get the following error,
followed by a segmentation fault. Which, I believe is due to a bug in
Qt.


qt.qpa.xcb: xcb_shm_create_segment() can't be called for size 17178820624, 
maximumallowed size is 4294967295


This only happen on applications that (try to) show a splash screen,
like fritzing and shortcut. And only happen on my machine that has a 4K
monitor.

Here's what I understand of what happen:

The application tries to show a window for the splash screen. The method
QXcbWindow::create() calls QXcbWindow::propagateSizeHints() which end up
calling xcb_icccm_size_hints_set_base_size with a size of (-2, -2).
We get these values because the window baseSize isn't initialized yet
and HiDPI-scaled.
These hints are then sent to the X server.

Those values are then sent back to the application as some
ConfigureNotify event (I believe) as a pair of uint16_t. This prompts Qt
to try to reallocate an unreasonably large buffer to accomodate the
"resized" window.

Here are the few lines of logs obtained with
QT_LOGGING_RULES='qt.qpa.*=true' right before the warning message that
lead to a crash.

qt.qpa.events: Event | XCB_PROPERTY_NOTIFY(28) | sequence: 402
qt.qpa.events: Event | XCB_PROPERTY_NOTIFY(28) | sequence: 402
qt.qpa.events: Event | XCB_CONFIGURE_NOTIFY(22) | sequence: 402
qt.qpa.xcb: [ QWidgetWindow(0x55751b9cc380, name="FSplashScreenClassWindow") ] 
creating shared memory 17178820624 bytes for QSize(65534, 65534) depth 24 bits 
32
qt.qpa.xcb: xcb_shm_create_segment() can't be called for size 17178820624, 
maximumallowed size is 4294967295


I don't know exactly why this only happen on some very specific
combinations of hardwares and softwares, but google tells me this bug
affects several applications and are always related to 4K monitors.
Could be also related to the window manager. I use fluxbox.

I'm not sure why the window baseSize is uninitialized, but in any case,
setting a negative base_size hint in QXcbWindow::propagateSizeHints()
sounds definitely like a bad idea. Maybe the values should be checked
before they are passed to xcb_icccm_size_hints_set_base_size, as is the
case with other hint values in the same method.

Unfortunately, I'm not well-versed enough in Qt to make an example
program. However, just to check that this is the cause of the bug, I
made a workaround using LD_PRELOAD to replace those negative hint values
with zeros. I attach the source code.

Compile with:
gcc -o preload.so -shared -fPIC preload.c -ldl -Wl,--no-as-needed -lxcb-icccm

Run with:
LD_PRELOAD=./preload.so fritzing


Best regards,
Celelibi


-- System Information:
Debian Release: bookworm/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'testing-debug'), (500, 'unstable'), 
(500, 'stable')
merged-usr: no
Architecture: amd64 (x86_64)

Kernel: Linux 5.18.0-4-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_FIRMWARE_WORKAROUND, 
TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages libqt5gui5 depends on:
ii  fontconfig                        2.13.1-4.4
ii  libc6                             2.34-7
ii  libdrm2                           2.4.112-3
ii  libegl1                           1.5.0-1
ii  libfontconfig1                    2.13.1-4.4
ii  libfreetype6                      2.12.1+dfsg-3
ii  libgbm1                           22.2.0~rc3-1
ii  libgcc-s1                         12.2.0-1
ii  libgl1                            1.5.0-1
ii  libglib2.0-0                      2.73.3-3
ii  libharfbuzz0b                     2.7.4-1+b1
ii  libice6                           2:1.0.10-1
ii  libinput10                        1.21.0-1
ii  libjpeg62-turbo                   1:2.1.2-1
ii  libmd4c0                          0.4.8-1
ii  libmtdev1                         1.1.6-1
ii  libpng16-16                       1.6.37-5
ii  libqt5core5a [qtbase-abi-5-15-4]  5.15.4+dfsg-5
ii  libqt5dbus5                       5.15.4+dfsg-5
ii  libqt5network5                    5.15.4+dfsg-5
ii  libsm6                            2:1.2.3-1
ii  libstdc++6                        12.2.0-1
ii  libudev1                          251.4-3
ii  libx11-6                          2:1.8.1-2
ii  libx11-xcb1                       2:1.8.1-2
ii  libxcb-glx0                       1.15-1
ii  libxcb-icccm4                     0.4.1-1.1
ii  libxcb-image0                     0.4.0-2
ii  libxcb-keysyms1                   0.4.0-1+b2
ii  libxcb-randr0                     1.15-1
ii  libxcb-render-util0               0.3.9-1+b1
ii  libxcb-render0                    1.15-1
ii  libxcb-shape0                     1.15-1
ii  libxcb-shm0                       1.15-1
ii  libxcb-sync1                      1.15-1
ii  libxcb-xfixes0                    1.15-1
ii  libxcb-xinerama0                  1.15-1
ii  libxcb-xinput0                    1.15-1
ii  libxcb-xkb1                       1.15-1
ii  libxcb1                           1.15-1
ii  libxkbcommon-x11-0                1.4.1-1
ii  libxkbcommon0                     1.4.1-1
ii  libxrender1                       1:0.9.10-1.1
ii  zlib1g                            1:1.2.11.dfsg-4.1

Versions of packages libqt5gui5 recommends:
ii  libqt5svg5             5.15.4-2
pn  qt5-gtk-platformtheme  <none>

Versions of packages libqt5gui5 suggests:
pn  qt5-image-formats-plugins  <none>
pn  qtwayland5                 <none>

-- no debconf information
/* gcc -o preload.so -shared -fPIC preload.c -ldl -Wl,--no-as-needed 
-lxcb-icccm */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

#include <xcb/xcb_icccm.h>




static void (*xcb_icccm_size_hints_set_base_size_orig)(xcb_size_hints_t *, 
int32_t, int32_t) = NULL;


void xcb_icccm_size_hints_set_base_size(xcb_size_hints_t *hints, int32_t 
base_width, int32_t base_height) {
        printf("xcb_icccm_size_hints_set_base_size called with %d %d\n", 
base_width, base_height);

        if (xcb_icccm_size_hints_set_base_size_orig == NULL) {
                *(void **)&xcb_icccm_size_hints_set_base_size_orig = 
dlsym(RTLD_NEXT, "xcb_icccm_size_hints_set_base_size");
                fprintf(stderr, "xcb_icccm_size_hints_set_base_size found at 
0x%08lx\n", (uintptr_t)xcb_icccm_size_hints_set_base_size_orig);
                if (xcb_icccm_size_hints_set_base_size_orig == NULL)
                        abort();
        }

        if (base_width < 0)
                base_width = 0;
        if (base_height < 0)
                base_height = 0;

        xcb_icccm_size_hints_set_base_size_orig(hints, base_width, base_height);
}

Reply via email to