Skip to content

stackable-box: Don't access free'd ChildInfo

Guido Günther requested to merge guidog/libhandy:use-after-free into main

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.

Edited by Guido Günther

Merge request reports

Loading