After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 418531 - invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon(), might cause gnome-panel crash
invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon(), might cause gnom...
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: Other
2.10.x
Other Linux
: Normal critical
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2007-03-15 11:20 UTC by Sebastien Bacher
Modified: 2007-04-24 15:00 UTC
See Also:
GNOME target: ---
GNOME version: 2.17/2.18


Attachments
Handle recursing into ensure_valid_themes() (4.64 KB, patch)
2007-03-15 12:43 UTC, Chris Wilson
accepted-commit_now Details | Review

Description Sebastien Bacher 2007-03-15 11:20:38 UTC
The bug has been pointed with valgrind on GNOME 2.18.0, it might be the cause of the gnome-panel crasher already mentionned to bug #409101

==1171== Invalid read of size 1
==1171==    at 0x402255E: strcmp (mc_replace_strmem.c:341)
==1171==    by 0x48717B3: g_str_equal (gstring.c:77)
==1171==    by 0x48489FE: g_hash_table_insert (ghash.c:240)
==1171==    by 0x4386F97: ensure_valid_themes (gtkicontheme.c:1133)
==1171==    by 0x438766F: gtk_icon_theme_lookup_icon (gtkicontheme.c:1268)
==1171==    by 0x807D3C9: panel_find_icon (panel-util.c:640)
==1171==    by 0x807D468: panel_load_icon (panel-util.c:668)
==1171==    by 0x806F46C: button_widget_reload_pixbuf (button-widget.c:187)
==1171==    by 0x806F515: button_widget_icon_theme_changed (button-widget.c:210)
==1171==    by 0x48049D8: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==1171==    by 0x47F762A: g_closure_invoke (gclosure.c:490)
==1171==    by 0x4808102: signal_emit_unlocked_R (gsignal.c:2440)
==1171==    by 0x4809626: g_signal_emit_valist (gsignal.c:2199)
==1171==    by 0x48097E8: g_signal_emit (gsignal.c:2243)
==1171==    by 0x438629F: do_theme_change (gtkicontheme.c:624)
==1171==    by 0x4386AE4: gtk_icon_theme_rescan_if_needed (gtkicontheme.c:1725)
==1171==    by 0x4386EDD: ensure_valid_themes (gtkicontheme.c:1192)
==1171==    by 0x438766F: gtk_icon_theme_lookup_icon (gtkicontheme.c:1268)
==1171==    by 0x807D3C9: panel_find_icon (panel-util.c:640)
==1171==    by 0x807D468: panel_load_icon (panel-util.c:668)
==1171==    by 0x806F46C: button_widget_reload_pixbuf (button-widget.c:187)
==1171==    by 0x806F515: button_widget_icon_theme_changed (button-widget.c:210)
==1171==    by 0x48049D8: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==1171==    by 0x47F770C: g_closure_invoke (gclosure.c:490)
==1171==    by 0x4808102: signal_emit_unlocked_R (gsignal.c:2440)
==1171==    by 0x4809626: g_signal_emit_valist (gsignal.c:2199)
==1171==    by 0x48097E8: g_signal_emit (gsignal.c:2243)
==1171==    by 0x438629F: do_theme_change (gtkicontheme.c:624)
==1171==    by 0x4386AE4: gtk_icon_theme_rescan_if_needed (gtkicontheme.c:1725)
==1171==    by 0x4386EDD: ensure_valid_themes (gtkicontheme.c:1192)
==1171==    by 0x438766F: gtk_icon_theme_lookup_icon (gtkicontheme.c:1268)
==1171==    by 0x807D3C9: panel_find_icon (panel-util.c:640)
==1171==    by 0x807D468: panel_load_icon (panel-util.c:668)
==1171==    by 0x806F46C: button_widget_reload_pixbuf (button-widget.c:187)
==1171==    by 0x806F515: button_widget_icon_theme_changed (button-widget.c:210)
==1171==    by 0x48049D8: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==1171==    by 0x47F762A: g_closure_invoke (gclosure.c:490)
==1171==    by 0x4808102: signal_emit_unlocked_R (gsignal.c:2440)
==1171==    by 0x4809626: g_signal_emit_valist (gsignal.c:2199)
==1171==    by 0x48097E8: g_signal_emit (gsignal.c:2243)
==1171==  Address 0x7415230 is 0 bytes inside a block of size 7 free'd
==1171==    at 0x402123A: free (vg_replace_malloc.c:233)
==1171==    by 0x485C130: g_free (gmem.c:187)
==1171==    by 0x4848910: g_hash_table_replace (ghash.c:390)
==1171==    by 0x4385373: insert_theme (gtkicontheme.c:2219)
==1171==    by 0x438515A: insert_theme (gtkicontheme.c:995)
==1171==    by 0x438515A: insert_theme (gtkicontheme.c:995)
==1171==    by 0x438515A: insert_theme (gtkicontheme.c:995)
==1171==    by 0x438515A: insert_theme (gtkicontheme.c:995)
==1171==    by 0x4386BCE: ensure_valid_themes (gtkicontheme.c:1045)
==1171==    by 0x438766F: gtk_icon_theme_lookup_icon (gtkicontheme.c:1268)
==1171==    by 0x807D3C9: panel_find_icon (panel-util.c:640)
==1171==    by 0x807D468: panel_load_icon (panel-util.c:668)
==1171==    by 0x806F46C: button_widget_reload_pixbuf (button-widget.c:187)
==1171==    by 0x806F515: button_widget_icon_theme_changed (button-widget.c:210)
==1171==    by 0x48049D8: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==1171==    by 0x47F762A: g_closure_invoke (gclosure.c:490)
==1171==    by 0x4808102: signal_emit_unlocked_R (gsignal.c:2440)
==1171==    by 0x4809626: g_signal_emit_valist (gsignal.c:2199)
==1171==    by 0x48097E8: g_signal_emit (gsignal.c:2243)
==1171==    by 0x438629F: do_theme_change (gtkicontheme.c:624)
==1171==    by 0x4386AE4: gtk_icon_theme_rescan_if_needed (gtkicontheme.c:1725)
==1171==    by 0x4386EDD: ensure_valid_themes (gtkicontheme.c:1192)
==1171==    by 0x438766F: gtk_icon_theme_lookup_icon (gtkicontheme.c:1268)
==1171==    by 0x807D3C9: panel_find_icon (panel-util.c:640)
==1171==    by 0x807D468: panel_load_icon (panel-util.c:668)
==1171==    by 0x806F46C: button_widget_reload_pixbuf (button-widget.c:187)
==1171==    by 0x806F515: button_widget_icon_theme_changed (button-widget.c:210)
==1171==    by 0x48049D8: g_cclosure_marshal_VOID__VOID (gmarshal.c:77)
==1171==    by 0x47F770C: g_closure_invoke (gclosure.c:490)
==1171==    by 0x4808102: signal_emit_unlocked_R (gsignal.c:2440)
==1171==    by 0x4809626: g_signal_emit_valist (gsignal.c:2199)
==1171==    by 0x48097E8: g_signal_emit (gsignal.c:2243)
==1171==    by 0x438629F: do_theme_change (gtkicontheme.c:624)
==1171==    by 0x4386AE4: gtk_icon_theme_rescan_if_needed (gtkicontheme.c:1725)
==1171==    by 0x4386EDD: ensure_valid_themes (gtkicontheme.c:1192)
==1171==    by 0x438766F: gtk_icon_theme_lookup_icon (gtkicontheme.c:1268)
==1171==    by 0x807D3C9: panel_find_icon (panel-util.c:640)
==1171==    by 0x807D468: panel_load_icon (panel-util.c:668)
==1171==    by 0x806F46C: button_widget_reload_pixbuf (button-widget.c:187)
==1171==    by 0x806F515: button_widget_icon_theme_changed (button-widget.c:210)
Comment 1 Chris Wilson 2007-03-15 12:43:38 UTC
Created attachment 84639 [details] [review]
Handle recursing into ensure_valid_themes()

Nasty bit of recursion into ensure_valid_themes().

The patch moves the 'theme-changed' emission til after the ensure_valid_themes() has reload the theme and performs no work if called recursively. This allows apps to reload their icons from within the theme changed handler without triggering further work. Though in this case the first caller would blow_themes() and the second caller would load_themes() and not trigger the broadcast.
Comment 2 Chris Wilson 2007-03-15 12:58:05 UTC
* tries to rewrite the previous comment, trying this time to make sense.

The patch moves the 'theme-changed' emission til after the
ensure_valid_themes() has reloaded the theme and performs no work if called
recursively. This should allows apps to reload their icons from within the theme
changed handler without rescanning the theme directories.
Comment 3 Matthias Clasen 2007-03-15 18:26:25 UTC
Thanks, that looks good. 

Please commit to both branches.
Comment 4 Chris Wilson 2007-03-15 18:46:55 UTC
Committed to gtk+-2.10 r17522 and trunk r17523:

2007-03-15  Chris Wilson  <chris@chris-wilson.co.uk>

	* gtk/gtkicontheme.c (ensure_valid_themes), (rescan_themes),
	(gtk_icon_theme_rescan_if_needed): Protect ensure_valid_themes()
	from recursion, which can happen for example if the app tries to
	reload an icon from within a theme-changed handler. (#418531)

Comment 5 Matthias Clasen 2007-03-15 21:21:05 UTC
Thanks
Comment 6 Chris Wilson 2007-03-15 21:34:49 UTC
Sorry Matthias, I didn't immediately close this bug as I felt the recursion was only half the problem.

I've been able to trigger recursion within the unpatched ensure_valid_themes() by touching an icon directory before calling gtk_icon_theme_lookup_icon() within the theme-changed handler. However it doesn't die with the same segfault. 

At the moment I can't see how that stack got into the mess it did, so I'd leave the code as is until we get a new bug report with a nice clean stack trace...
Comment 7 Sebastien Bacher 2007-03-30 11:32:11 UTC
That's still happening with a patched GTK 2.10.11, reopening
Comment 8 Chris Wilson 2007-03-30 11:45:40 UTC
Sebastien, is the stacktrace identical?
Comment 9 Sebastien Bacher 2007-04-04 08:18:41 UTC
Look similar:

==6332== Invalid read of size 1
==6332==    at 0x402257E: strcmp (mc_replace_strmem.c:341)
==6332==    by 0x48737B3: g_str_equal (gstring.c:77)
==6332==    by 0x484A9FE: g_hash_table_insert (ghash.c:240)
==6332==    by 0x438661E: insert_theme (gtkicontheme.c:2244)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x43876BE: ensure_valid_themes (gtkicontheme.c:1047)
==6332==    by 0x4387B51: _gtk_icon_theme_check_reload (gtkicontheme.c:3097)
==6332==    by 0x44E8D36: gtk_window_client_event (gtkwindow.c:4873)
==6332==    by 0x43BE6AF: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:84)
==6332==    by 0x47F7E48: g_type_class_meta_marshal (gclosure.c:567)
==6332==    by 0x47F962A: g_closure_invoke (gclosure.c:490)
==6332==    by 0x480A752: signal_emit_unlocked_R (gsignal.c:2478)
==6332==    by 0x480B3EE: g_signal_emit_valist (gsignal.c:2209)
==6332==    by 0x480B7E8: g_signal_emit (gsignal.c:2243)
==6332==    by 0x44D2E17: gtk_widget_event_internal (gtkwidget.c:3915)
==6332==    by 0x43B8CB8: gtk_main_do_event (gtkmain.c:1576)
==6332==    by 0x4618129: gdk_event_dispatch (gdkevents-x11.c:2318)
==6332==    by 0x4856DF1: g_main_context_dispatch (gmain.c:2045)
==6332==    by 0x4859DCE: g_main_context_iterate (gmain.c:2677)
==6332==    by 0x485A178: g_main_loop_run (gmain.c:2881)
==6332==    by 0x43B9043: gtk_main (gtkmain.c:1177)
==6332==    by 0x806399B: main (main.c:98)
==6332==  Address 0x89A4A11 is 1 bytes inside a block of size 7 free'd
==6332==    at 0x402123A: free (vg_replace_malloc.c:233)
==6332==    by 0x485E130: g_free (gmem.c:187)
==6332==    by 0x484A910: g_hash_table_replace (ghash.c:390)
==6332==    by 0x4386643: insert_theme (gtkicontheme.c:2245)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x438642A: insert_theme (gtkicontheme.c:997)
==6332==    by 0x43876BE: ensure_valid_themes (gtkicontheme.c:1047)
==6332==    by 0x4387B51: _gtk_icon_theme_check_reload (gtkicontheme.c:3097)
==6332==    by 0x44E8D36: gtk_window_client_event (gtkwindow.c:4873)
==6332==    by 0x43BE6AF: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:84)
==6332==    by 0x47F7E48: g_type_class_meta_marshal (gclosure.c:567)
==6332==    by 0x47F962A: g_closure_invoke (gclosure.c:490)
==6332==    by 0x480A752: signal_emit_unlocked_R (gsignal.c:2478)
==6332==    by 0x480B3EE: g_signal_emit_valist (gsignal.c:2209)
==6332==    by 0x480B7E8: g_signal_emit (gsignal.c:2243)
==6332==    by 0x44D2E17: gtk_widget_event_internal (gtkwidget.c:3915)
==6332==    by 0x43B8CB8: gtk_main_do_event (gtkmain.c:1576)
==6332==    by 0x4618129: gdk_event_dispatch (gdkevents-x11.c:2318)
==6332==    by 0x4856DF1: g_main_context_dispatch (gmain.c:2045)
==6332==    by 0x4859DCE: g_main_context_iterate (gmain.c:2677)
==6332==    by 0x485A178: g_main_loop_run (gmain.c:2881)
==6332==    by 0x43B9043: gtk_main (gtkmain.c:1177)
==6332==    by 0x806399B: main (main.c:98)
Comment 10 Chris Wilson 2007-04-04 08:56:03 UTC
Aye, it's the same bug without the nasty recursion...

Sebastien, I think I can finally see what the real problem is here... The two keys for icon_theme->all_icons and dir->icons must be kept synced as they share the same string. So by inserting in the first we kept the original string, but then freed it when replacing in the second... Bang.

Trivial patch to try:
Index: gtk/gtkicontheme.c
===================================================================
--- gtk/gtkicontheme.c  (revision 17549)
+++ gtk/gtkicontheme.c  (working copy)
@@ -2241,7 +2241,7 @@ scan_directory (GtkIconThemePrivate *ico
       base_name = strip_suffix (name);
 
       hash_suffix = GPOINTER_TO_INT (g_hash_table_lookup (dir->icons, base_name));
-      g_hash_table_insert (icon_theme->all_icons, base_name, NULL);
+      g_hash_table_replace (icon_theme->all_icons, base_name, NULL);
       g_hash_table_replace (dir->icons, base_name, GUINT_TO_POINTER (hash_suffix| suffix));
     }
Comment 11 Sebastien Bacher 2007-04-05 15:58:36 UTC
the new patch seems to work correctly, no valgrind error with it
Comment 12 Chris Wilson 2007-04-24 15:00:58 UTC
Applied to 2.10 (r17625) and trunk (r17626):
2007-04-24  Chris Wilson  <chris@chris-wilson.co.uk>

	* gtk/gtkicontheme.c (scan_directory): Ensure the 
	icon_theme->all_icons and dir->icons hash tables use the same string
	as their keys. (#418531)