Public bug reported:
This issue happens sometimes but it's not enough to be considered a
serious issue. It's more of an annoyance when it happens but it still
should be fixed either way.
The issue is a Use-after-free bug in gtk_widget_dispose() due to in_destruction
flag cleared too early
=============================================================================================
Affected Versions
-----------------
| Version | Status |
|---------|--------|
| GTK 4.22.2 (libgtk-4-1 4.22.2+ds-1ubuntu1) | Confirmed vulnerable (installed)
|
| GTK 4.22.4 (4.22.4+ds-0ubuntu0.1) | Still vulnerable (latest available,
checked source) |
The gtk-4-22 branch has no commits addressing this issue as of 4.22.4.
Environment
-----------
- Distribution: Ubuntu 26.04
- Package: nautilus 1:50.0-0ubuntu2
- Crash: SIGSEGV (signal 11) in g_type_check_instance_is_fundamentally_a()
- Trigger: Closing a Nautilus window while a signal handler re-enters the parent
during destroy
Source Location
---------------
File: gtk/gtkwidget.c
| Function | Line (4.22.4) | Role |
|---|---|---|
| gtk_widget_dispose | 7638-7701 | Widget dispose handler |
| gtk_widget_real_destroy | 7721-7850 | Destroys template auto-children |
Root Cause
----------
In gtk_widget_dispose() at lines 7674-7679:
if (!priv->in_destruction)
{
priv->in_destruction = TRUE;
g_signal_emit (object, widget_signals[DESTROY], 0);
priv->in_destruction = FALSE; // BUG: cleared too early (line
7678)
gtk_widget_real_destroy (widget); // children freed here (line
7679)
}
Then in gtk_widget_real_destroy():
- Line 7816: g_hash_table_remove(auto_child_hash, child_class->name)
drops the last reference on template child widgets, triggering their full
dispose() -> finalize() chain
- Line 7823: g_clear_pointer(&auto_children, g_hash_table_unref)
crashes because children already freed via re-entrant destruction
Since in_destruction is FALSE when real_destroy runs, if a child's finalization
emits a signal that calls back into the parent widget (which is mid-destruction
but no longer protected), the parent's state can be corrupted or doubly-freed,
resulting in a SIGSEGV in g_type_check_instance_is_fundamentally_a() ->
g_object_unref().
Crash Stack (from Nautilus core dump)
--------------------------------------
#0 g_type_check_instance_is_fundamentally_a() invalid instance pointer
#1 g_object_unref()
#2 g_hash_table_unref() auto_children table (line
7823)
#3 g_hash_table_unref()
#4 gtk_widget_real_destroy() line 7823
#5 g_signal_emit() -> g_closure_invoke() re-entrant signal
#6 gtk_widget_dispose() re-entered, no protection
#7 g_object_unref() child's last ref dropped
#8 g_hash_table_remove() line 7816
#9 gtk_widget_real_destroy() line 7679
#10 gtk_widget_dispose() line 7674-7679
Fix
---
Move priv->in_destruction = FALSE to AFTER gtk_widget_real_destroy()
completes:
if (!priv->in_destruction)
{
priv->in_destruction = TRUE;
g_signal_emit (object, widget_signals[DESTROY], 0);
- priv->in_destruction = FALSE;
gtk_widget_real_destroy (widget);
+ priv->in_destruction = FALSE;
}
This ensures the parent remains protected by in_destruction while its children
are being torn down, preventing re-entrant destruction from corrupting the
parent's internal hash tables.
** Affects: gtk4 (Ubuntu)
Importance: Undecided
Status: New
** Tags: crash gtk4 in-destruction nautilus sigsegv use-after-free
widget-dispose
--
You received this bug notification because you are a member of Ubuntu
Desktop Bugs, which is subscribed to gtk4 in Ubuntu.
https://bugs.launchpad.net/bugs/2156579
Title:
Use after free bug in gtkwiget.c
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gtk4/+bug/2156579/+subscriptions
--
desktop-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/desktop-bugs