https://bugs.kde.org/show_bug.cgi?id=523257

            Bug ID: 523257
           Summary: KWin transiently advertises an invalid 0×0 output size
                    (wl_output.mode / xdg_output.logical_size), crashing
                    strict clients (Xwayland + libxcvt >= 0.1.3-git)
    Classification: Plasma
           Product: kwin
      Version First 6.7.3
       Reported In:
          Platform: CachyOS
                OS: Linux
            Status: REPORTED
          Severity: major
          Priority: NOR
         Component: xwayland
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

**Summary**

Disclaimer: The debugging, technical analysis and write-up was done by an AI
agent. However, I verified that the proposed changes on the xorg-xwayland-side
and the KWin-side fixed the problem for me with latest libxcvt-git.

Upgrading to latest libxcvt-git revealed a bug in xorg-xwayland (filed as:
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1910). There is also a
KWin component to it which this bug report is about. KWin can send a degenerate
output size — `wl_output.mode` with `width=0`/`height=0`, and/or
`zxdg_output_v1.logical_size` with `0` — during a transient window (output
enable, hotplug, or VRR/adaptive-sync mode change). Both fields are defined by
the protocol as positive pixel extents, so this is protocol‑invalid.

Strict clients break on it. In particular Xwayland (with latest libxcvt
0.1.3-git) passes the size to `libxcvt_gen_mode_info()`, which now correctly
returns `NULL` for a non‑positive size, and Xwayland then aborts the **entire**
X server — taking down every X11 app in the session. KWin gives up after 4
restarts. Older libxcvt (≤ 0.1.3+3) returned a *garbage* mode instead of NULL,
which merely hid this protocol violation.

**Where (KWin source)**

- `OutputInterfacePrivate::sendMode()` — `src/wayland/output.cpp`
  Sends `modeSize.width()/height()`. `modeSize` is a default‑constructed
(empty) `QSize` until `setData()`/`currentModeChanged`, and is (re)sent on
client bind and on mode change. No positivity guard.
- `XdgOutputV1Interface::sendLogicalSize()` — `src/wayland/xdgoutput_v1.cpp`
  Sends `size = handle->geometryF().size()`, which can be empty during
(re)configuration. This is the field Xwayland prefers for its RandR mode size.
No positivity guard.

**Impact / trigger**

Reproducible on AMD Vega 64 (amdgpu) driving an HP X27q (VRR 48–165 Hz): VRR
mode‑flapping / output reconfiguration produces the transient 0×0, and Xwayland
dies deterministically on each startup, leading to a flawed and laggy desktop
experience.

**Downstream Xwayland crash (from `journalctl`)**

Uncontrolled form (NULL deref of the libxcvt result; offset `0x10` is `struct
libxcvt_mode_info::dot_clock`):

```
kwin_wayland_wrapper[1254]: (EE) 3: /usr/bin/Xwayland (0x55c111000000+0x2899ab)
[0x55c1112899ab]
kwin_wayland_wrapper[1254]: (EE) 4: /usr/bin/Xwayland (0x55c111000000+0x28d1b2)
[0x55c11128d1b2]
kwin_wayland_wrapper[1254]: (EE) 5: /usr/lib/libffi.so.8
(0x55c11106a000+0x9876) [0x55c111073876]
kwin_wayland_wrapper[1254]: (EE) 6: /usr/lib/libffi.so.8
(0x55c11106a000+0x4e29) [0x55c11106ee29]
kwin_wayland_wrapper[1254]: (EE) 7: /usr/lib/libffi.so.8 (ffi_call+0x166)
[0x55c111072606]
kwin_wayland_wrapper[1254]: (EE) 8: /usr/lib/libwayland-client.so.0
(0x55c110000000+0x205e86) [0x55c110205e86]
kwin_wayland_wrapper[1254]: (EE) 9: /usr/lib/libwayland-client.so.0
(wl_display_dispatch_queue_timeout+0x198) [0x55c1102057f8]
kwin_wayland_wrapper[1254]: (EE) 10: /usr/lib/libwayland-client.so.0
(wl_display_dispatch+0xf) [0x55c11020562f]
kwin_wayland_wrapper[1254]: (EE) 11: /usr/bin/Xwayland
(0x55c111000000+0x2a44f5) [0x55c1112a44f5]
kwin_wayland_wrapper[1254]: (EE) Segmentation fault at address 0x10
kwin_wayland_wrapper[1254]: (EE) Caught signal 11 (Segmentation fault). Server
aborting
```

Frame 3 (`Xwayland+0x2899ab`) is `xwayland_modeinfo_from_cvt()`; the faulting
instruction is `mov 0x10(%rax),%rdx` with `%rax = NULL`, i.e. the return of
`libxcvt_gen_mode_info()` (reached via `wl_display_dispatch` → `ffi_call`
marshalling a Wayland output event).

Once Xwayland is given a NULL check it instead FatalErrors, still killing the
server:

```
kwin_wayland_wrapper[1262]: Fatal server error:
kwin_wayland_wrapper[1262]: (EE) Failed to allocate memory for list of RR
modes(EE)
kwin_wayland[1195]: Stopping Xwayland server because it has crashed 4 times
over the past 10 minutes
```

**Suggested fix (defense‑in‑depth, zero hot‑path cost)**

Never emit a non‑positive output size; skip the send until a valid size is
known — a follow‑up `currentModeChanged` / `resend()` delivers the correct
value. `OutputInterface` is only created for already‑enabled outputs, so this
is a no‑op in the normal case and only fires in the pathological transient
window:

```cpp
// OutputInterfacePrivate::sendMode()  — src/wayland/output.cpp
if (modeSize.width() <= 0 || modeSize.height() <= 0)
    return;

// XdgOutputV1Interface::sendLogicalSize()  — src/wayland/xdgoutput_v1.cpp
if (size.width() <= 0 || size.height() <= 0)
    return;
```

These run only on output (re)configuration / client bind, never per‑frame —
O(1), no measurable performance impact. Sending a valid mode is unchanged.

**Related**

- Xwayland side (the client that crashes):
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1910
- libxcvt change that exposed this: commit `23c30d4` "Avoid potential division
by zero" (MR!22) — returns NULL for `hdisplay/vdisplay <= 0`. This is correct;
not a libxcvt bug (the old code did `x % 0` / `1/0` and returned garbage).

**Environment**

KWin 6.7.3 (Wayland) · Xwayland 24.1.6 · libxcvt‑git 0.1.3+8 · Mesa/amdgpu
(Vega10) · HP X27q (2560×1440, VRR 48–165 Hz) · CachyOS.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to