From 8442f54e896ebee81d2f0ad659e0eac74995689e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sun, 30 Jun 2024 15:28:04 +0200 Subject: [PATCH] stackable-box: Don't access free'd ChildInfo When the container is being destroyed `hdy_stackable_box_remove` invokes `set_visible_child_info` for the currently shown child. However that returns early due to the `gtk_widget_in_destruction` check. The ChildInfo is free'd nevertheless when leaving `hdy_stackable_box_remove` When the next child is removed `hdy_stackable_box_remove` invokes `hdy_stackable_box_get_visible_child` but `self->visible_child` points to the just free'd child info leading to this invalid read: ==273448== Invalid read of size 8 ==273448== at 0x597FCAB: hdy_stackable_box_get_visible_child (hdy-stackable-box.c:952) ==273448== by 0x597FCAB: hdy_stackable_box_remove (hdy-stackable-box.c:2317) ==273448== by 0x5728E24: g_cclosure_marshal_VOID__OBJECTv (gmarshal.c:1910) ==273448== by 0x5725938: _g_closure_invoke_va (gclosure.c:897) ==273448== by 0x573B33E: signal_emit_valist_unlocked (gsignal.c:3424) ==273448== by 0x5740F05: g_signal_emit_valist (gsignal.c:3263) ==273448== by 0x5740FC2: g_signal_emit (gsignal.c:3583) ==273448== by 0x4B6CB59: gtk_container_remove (gtkcontainer.c:1907) ==273448== by 0x4DA8397: gtk_widget_dispose (gtkwidget.c:12155) ==273448== by 0x572D0C2: g_object_run_dispose (gobject.c:1842) ==273448== by 0x597FDCA: hdy_stackable_box_forall (hdy-stackable-box.c:2348) ==273448== by 0x4B6E8BB: gtk_container_destroy (gtkcontainer.c:1702) ==273448== by 0x5725694: g_closure_invoke (gclosure.c:834) ==273448== Address 0xf6dca40 is 0 bytes inside a block of size 64 free'd ==273448== at 0x48431EF: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==273448== by 0x5728E24: g_cclosure_marshal_VOID__OBJECTv (gmarshal.c:1910) ==273448== by 0x5725938: _g_closure_invoke_va (gclosure.c:897) ==273448== by 0x573B33E: signal_emit_valist_unlocked (gsignal.c:3424) ==273448== by 0x5740F05: g_signal_emit_valist (gsignal.c:3263) ==273448== by 0x5740FC2: g_signal_emit (gsignal.c:3583) ==273448== by 0x4B6CB59: gtk_container_remove (gtkcontainer.c:1907) ==273448== by 0x4DA8397: gtk_widget_dispose (gtkwidget.c:12155) ==273448== by 0x572D0C2: g_object_run_dispose (gobject.c:1842) ==273448== by 0x597FDCA: hdy_stackable_box_forall (hdy-stackable-box.c:2348) ==273448== by 0x4B6E8BB: gtk_container_destroy (gtkcontainer.c:1702) ==273448== by 0x5725694: g_closure_invoke (gclosure.c:834) ==273448== Block was alloc'd at ==273448== at 0x48459F3: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==273448== by 0x57D3E29: g_malloc0 (gmem.c:133) ==273448== by 0x5980ADC: hdy_stackable_box_insert_child_after (hdy-stackable-box.c:2916) ==273448== by 0x5728E24: g_cclosure_marshal_VOID__OBJECTv (gmarshal.c:1910) ==273448== by 0x5725938: _g_closure_invoke_va (gclosure.c:897) ==273448== by 0x573B33E: signal_emit_valist_unlocked (gsignal.c:3424) ==273448== by 0x5740F05: g_signal_emit_valist (gsignal.c:3263) ==273448== by 0x5740FC2: g_signal_emit (gsignal.c:3583) ==273448== by 0x4B6C9D4: gtk_container_add (gtkcontainer.c:1877) ==273448== by 0x4B6C9D4: gtk_container_add (gtkcontainer.c:1856) ==273448== by 0x4B24EA1: _gtk_builder_add (gtkbuilder.c:906) ==273448== by 0x4B29955: parse_custom (gtkbuilderparser.c:892) ==273448== by 0x4B29955: start_element (gtkbuilderparser.c:985) ==273448== by 0x57D0C2B: emit_start_element (gmarkup.c:1010) Fix this by clearing self->visible_child in `set_visible_child_info` during destruction. --- src/hdy-stackable-box.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hdy-stackable-box.c b/src/hdy-stackable-box.c index 9a5db7d5..dbee6a1c 100644 --- a/src/hdy-stackable-box.c +++ b/src/hdy-stackable-box.c @@ -485,8 +485,10 @@ set_visible_child_info (HdyStackableBox *self, /* If we are being destroyed, do not bother with transitions and * notifications. */ - if (gtk_widget_in_destruction (widget)) + if (gtk_widget_in_destruction (widget)) { + self->visible_child = NULL; return; + } /* If none, pick first visible. */ if (new_visible_child == NULL) { -- GitLab