From fb829c8a8e037fd8631af94dc2f888075612d1d0 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Tue, 9 Jun 2026 06:20:05 +0000 Subject: [PATCH] ## fix(niri/workspaces): crash (segfault) when setting workspace button markup ### Problem Waybar segfaults on startup when `niri/workspaces` is the only configured module (default options). Right after the first `WorkspacesChanged` event: Thread 1 "waybar" received signal SIGSEGV #0 gtk_label_set_markup () #1 waybar::modules::niri::Workspaces::doUpdate () at src/modules/niri/workspaces.cpp:106 ### Root cause [doUpdate()](cci:1://file:///home/lj/Downloads/Waybar/src/modules/niri/window.cpp:27:0-90:1) set the label markup via: static_cast(button.get_children()[0])->set_markup(name); The button's child *is* a valid `GtkLabel`, but gtkmm's `get_children()` returns it wrapped as a generic `Gtk::Widget` (confirmed: `dynamic_cast` to `Gtk::Label*` yields `nullptr`). The unchecked `static_cast` then performs an invalid downcast, producing a corrupt pointer whose `gobj()` is garbage (`0x1`), so `gtk_label_set_markup()` dereferences it and crashes. This is reliably triggered when no other module has instantiated a `Gtk::Label` yet (so the `Gtk::Label` wrapper isn't registered), which is exactly the case for a `niri/workspaces`-only bar. The same idiom exists in `sway/workspaces` and `wayfire/workspaces`; it's masked there because typical configs include other label-using modules. ### Testing - Reproduced the crash on 0.15.0 / current `master` with a minimal `"modules-left": ["niri/workspaces"]` config under niri. - After the fix: no crash; three workspace buttons render with correct names/labels (`niri-workspace-1/2/3`). --- src/modules/niri/workspaces.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/niri/workspaces.cpp b/src/modules/niri/workspaces.cpp index 97d15215a..a817ab9cb 100644 --- a/src/modules/niri/workspaces.cpp +++ b/src/modules/niri/workspaces.cpp @@ -103,7 +103,9 @@ void Workspaces::doUpdate() { fmt::arg("output", ws["output"].asString())); } if (!config_["disable-markup"].asBool()) { - static_cast(button.get_children()[0])->set_markup(name); + auto* child = gtk_bin_get_child(GTK_BIN(button.gobj())); + if (child != nullptr && GTK_IS_LABEL(child)) + gtk_label_set_markup(GTK_LABEL(child), name.c_str()); } else { button.set_label(name); }