[Bug]: wayland: segfault on resize when cairo produces an invalid (nil) surface
What happened?
I run conky desktop widgets on KDE Plasma (Wayland), and the process started crashing with SIGSEGV — usually during a resize or redraw, but once even while the widget sat idle after an earlier resize. I dug into the coredump and found a null-pointer dereference of data->pool in window_allocate_buffer(). This crash escapes every existing guard in the buffer path, so I don't think it's rare.
Reproduction
Intermittent, but I saw it three times in one session, at different PIDs. The first crash was on first run, right when a missing Lua module left the text metrics in a bad state. After fixing the module it crashed again anyway — which is how I knew the bug lives at the allocation site, not in the Lua path.
Root cause (confirmed via coredump, PID 4008)
The whole chain, step by step:
window_resize()callswindow_allocate_buffer().create_shm_surface_from_pool()callscairo_image_surface_create_for_data()with the (scaled) width/height.- If a dimension is ≤ 0, cairo doesn't return an error — it hands back its special nil surface with
CAIRO_STATUS_INVALID_SIZE. cairo_surface_set_user_data()fails on a nil surface (you can't attach user data to one), sodatanever gets attached.- Back in
window_allocate_buffer(),cairo_surface_get_user_data()returns NULL, and the code dereferences it atdata->pool = (i == 1) ? pool : nullptr;.
Why the existing guard can't catch it: window_allocate_buffer() only checks if (!window->shm_surface[i]), and the nil surface is a non-NULL pointer. Worse, the shm allocation can succeed with garbage dimensions — when both scaled dimensions are negative, stride = -1 but length = (-1) × (negative) = positive, so shm_pool_allocate() returns a valid mapping and the nil surface is built on top of it.
Expected behavior
A bad resize should never crash conky. It should log the problem, keep the last good frame, and retry on the next update — exactly what the Weston clients/window.c code this path was ported from does.
Proposed direction
Validate the buffer right at the allocation site: reject stride < 0 and length <= 0 before mapping, check cairo_surface_status() after surface creation, and check cairo_surface_set_user_data()'s return value. On any failure, return NULL so the existing !window->shm_surface[i] guard destroys the pool and keeps the previous buffers.
References
- cairo manual:
cairo_surface_set_user_data,cairo_surface_status(nil surfaces →CAIRO_STATUS_INVALID_SIZE). - Weston
clients/window.c: the buffer-management code this was ported from.
Related existing reports
- #1791 (closed) — a different Wayland crash (wl_dispatch race, fixed via #2198); different stack, not this NULL-deref.
- #1824 (closed) — another Wayland crash, reverted via #2104; also unrelated.
- cc1dc5d
fix(wayland): fix output scale race condition— fixed apending_scalerace whose garbage scaling is a plausible trigger of the invalid dimensions landing in this resize path. Citing as context, not a fix for the dereference itself.
I didn't find any open issue or PR covering the nil-surface NULL-deref in window_allocate_buffer().
Version
conky git master (Wayland build, as of 1affe0297 / June 2026), compiled with -DBUILD_WAYLAND=ON -DBUILD_LUA_CAIRO=ON -DBUILD_LUA_TEXT=ON.
Which OS/distro are you seeing the problem on?
Arch Linux
Conky config
conky.config = {
own_window = true,
own_window_type = 'desktop',
-- rendered via wlr-layer-shell on Wayland
}
The full config is a Lua Cairo dashboard (`own_window_type = 'desktop'`); I can attach it if needed.Stack trace
Paste of the coredump forensics (systemd-coredump, PID 4008):
Program terminated with signal SIGSEGV, Segmentation fault.
#0 window_allocate_buffer (window=0x...) at src/output/display-wayland.cc:1304
movq $0x0,0x8(%rax) # write to 0x8 == data->pool, with rax == 0 (data == NULL)
Backtrace:
#0 window_allocate_buffer
#1 window_resize
#2 display_output_wayland::main_loop_wait
#3 main_loop
#4 main
The cairo surface at fault symbolises as `_cairo_surface_nil_invalid_size`, i.e. `CAIRO_STATUS_INVALID_SIZE`. Struct layout confirms the write target: `buffer@0, pool@8, busy@16`.Relevant log output
# conky's own log at crash time (this path was only logging normal draw activity):
[info ] [src/display-wayland.cc] window resized ...
# systemd-coredump captured SIGSEGV for PID 4008, backtrace as above.
I can share the full coredump on request.Source: brndnmtthws/conky