vasnprintf SEGV when %s arg is NULL

David Jafferian David.Jafferian at Sun.COM
Mon Aug 14 19:49:15 EDT 2006


Hi -

After about two weeks of evenings, I finally got gnucash 2.0.1 built
and running on my Solaris 9 x86 PC.  But upon attempting to bring
up the Edit->Preferences dialog, it received a SIGSEGV :

libc.so.1`_waitid+0xc(2af4, 804615c, 0)
libthread.so.1`waitpid+0x5c()
libgnomeui-2.so.0.400.0`libgnomeui_segv_handle+0x75(b, 0, 8046250)
libthread.so.1`__sighndlr+0xf(b, 0, 8046250, d2ac64b0)
libthread.so.1`call_user_handler+0x1c3(b, 0, 8046250)
libthread.so.1`sigacthandler+0x51(b, 0, 8046250)
libglib-2.0.so.0.600.6`_g_gnulib_vasnprintf+0x537()
libglib-2.0.so.0.600.6`_g_gnulib_vasprintf+0x22(8046810, d22456cb, 8046844, a)
libglib-2.0.so.0.600.6`g_vasprintf+0x25()
libglib-2.0.so.0.600.6`g_strdup_vprintf+0x29()
libglib-2.0.so.0.600.6`g_strdup_printf+0x1f()
libcore-utils.so.0.0.0`gnc_gconf_add_notification+0x14e(ad10600, 0, d2cba31c)
libgncmod-gnome-utils.so.0.0.0`gnc_preferences_dialog+0x4d3()
libgncmod-gnome-utils.so.0.0.0`gnc_main_window_cmd_edit_preferences+0x16()
libgobject-2.0.so.0.600.6`g_cclosure_marshal_VOID__VOID+0x6b()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0xada()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x860()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23(81b7e68, 7e, 0, 0)
libgtk-x11-2.0.so.0.600.10`_gtk_action_emit_activate+0x46(81b7e68, d210754c, 8046db8, d1eb15b1)
libgtk-x11-2.0.so.0.600.10`gtk_action_activate+0x91()
libgobject-2.0.so.0.600.6`g_cclosure_marshal_VOID__VOID+0x6b()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0xada()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x860()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23()
libgtk-x11-2.0.so.0.600.10`gtk_widget_activate+0x90()
libgtk-x11-2.0.so.0.600.10`gtk_menu_shell_activate_item+0x101()
libgtk-x11-2.0.so.0.600.10`gtk_menu_shell_button_release+0x203()
libgtk-x11-2.0.so.0.600.10`gtk_menu_button_release+0x55()
libgtk-x11-2.0.so.0.600.10`_gtk_marshal_BOOLEAN__BOXED+0x79(80984b8, 80473e0, 2, 8047520, 8047408,d1f6c95c)
libgobject-2.0.so.0.600.6`g_type_class_meta_marshal+0x42()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0x64a()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x59d()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23(81cae98, 2b, 0, 81a7708, 80476c8, 80a61a0)
libgtk-x11-2.0.so.0.600.10`gtk_widget_event_internal+0xf2()
libgtk-x11-2.0.so.0.600.10`gtk_propagate_event+0xc3(81cae98, 81a7708, 8047758, d1f667c3)
libgtk-x11-2.0.so.0.600.10`gtk_main_do_event+0x1b8(81a7708, 0, 8084dc0, d1dfa029)
libgdk-x11-2.0.so.0.600.10`gdk_event_dispatch+0x92(8084d68, 0, 0, 0)
libglib-2.0.so.0.600.6`g_main_context_dispatch+0x1d5(8084db0, 0, 81a8780, 7)
libglib-2.0.so.0.600.6`g_main_context_iterate+0x413()
libglib-2.0.so.0.600.6`g_main_loop_run+0x19c()
libgtk-x11-2.0.so.0.600.10`gtk_main+0xa7()
libgncmod-gnome-utils.so.0.0.0`gnc_ui_start_event_loop+0x4e()
inner_main+0x136(0, 1, 8047bec, d1c25ae4)
libguile.so.12.3.1`scm_boot_guile+0x67(1, 8047bec, 8051dcc, 0, 1, 8047bec)
main+0x607(1, 8047bec, 8047bf4)
_start+0x5d()

Google provided an email exchange on this issue :

   Re: win32: gnulib/g_vsnprintf NULL handling

       * Date: Thu, 05 May 2005 07:38:00 -0400
       * From: Owen Taylor <otaylor at xxxxxxxxxx>
       * Subject: Re: win32: gnulib/g_vsnprintf NULL handling

   On Thu, 2005-05-05 at 10:49 +0200, Thorsten Maerz wrote:
   > Hi,
   > 
   > after upgrading from glib-2.2 to glib-2.6 the win32 version of
   > Sylpheed-Claws crashes when invoking g_vsnprintf() with a "%s"
   > format string and a NULL as argument.

   It would also crash on Solaris and many other platforms. Fix
   the app.

   Regards,
   					Owen

I believe Owen's blunt response to be somewhat justified, since it
would appear that the behavior of functions in the printf family is
specified to be undefined when the argument to a %s specifier is
NULL.  Some implementations will substitute a string such as
"(nil)" as an indicator, but the gnulib/glib implementation clearly
expects a valid pointer.

Rooting out the problem :

> d22456cb/s
0xd22456cb:     %s-client

>From "gnucash-2.0.1/src/core-utils/gnc-gconf-utils.c" :
void
gnc_gconf_add_notification (GObject *object,
			    const gchar *section,
			    GConfClientNotifyFunc callback)
...
	client_tag = g_strdup_printf(CLIENT_TAG, section);

"section" should not be NULL.

>From "gnucash-2.0.1/src/gnome-utils/dialog-preferences.c" :
void
gnc_preferences_dialog (void)
...
  gnc_gconf_add_notification(G_OBJECT(dialog), NULL,
			     gnc_preferences_gconf_changed);

It looks like that NULL has been there since this function was first
created, but something should replace it.  I don't know enough
about this code to suggest what should be put there, but replacing
NULL with "(nil)" made the crash go away.  Only problem left was
another SEGV crash upon closing the preferences dialog :

libc.so.1`_waitid+0xc(486, 8045e3c, 0)
libthread.so.1`waitpid+0x5c()
libgnomeui-2.so.0.400.0`libgnomeui_segv_handle+0x75(b, 0, 8045f30)
libthread.so.1`__sighndlr+0xf(b, 0, 8045f30, d2ac64b0)
libthread.so.1`call_user_handler+0x1c3(b, 0, 8045f30)
libthread.so.1`sigacthandler+0x51(b, 0, 8045f30)
libglib-2.0.so.0.600.6`_g_gnulib_vasnprintf+0x537()
libglib-2.0.so.0.600.6`_g_gnulib_vasprintf+0x22(80464f0, d22456cb, 8046524, e0000045)
libglib-2.0.so.0.600.6`g_vasprintf+0x25()
libglib-2.0.so.0.600.6`g_strdup_vprintf+0x29()
libglib-2.0.so.0.600.6`g_strdup_printf+0x1f()
libcore-utils.so.0.0.0`gnc_gconf_remove_notification+0x54()
libgncmod-gnome-utils.so.0.0.0`gnc_preferences_response_cb+0x61()
libgobject-2.0.so.0.600.6`g_cclosure_marshal_VOID__INT+0x71()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0xada()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x860()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23()
libgtk-x11-2.0.so.0.600.10`gtk_dialog_response+0x45()
libgtk-x11-2.0.so.0.600.10`action_widget_activated+0x29()
libgobject-2.0.so.0.600.6`g_cclosure_marshal_VOID__VOID+0x6b()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0xada()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x860()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23()
libgtk-x11-2.0.so.0.600.10`gtk_button_clicked+0x43(824aff0, 80a5480, 0, d1ebd118)
libgtk-x11-2.0.so.0.600.10`gtk_real_button_released+0x4c()
libgobject-2.0.so.0.600.6`g_cclosure_marshal_VOID__VOID+0x6b(8246a78, 0, 1, 80470b0, 8046f98, d1ebd108)
libgobject-2.0.so.0.600.6`g_type_class_meta_marshal+0x42()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0x436()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x860()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23()
libgtk-x11-2.0.so.0.600.10`gtk_button_released+0x43(824aff0, 0, 8047278, d1ebc79d)
libgtk-x11-2.0.so.0.600.10`gtk_button_button_release+0x2f()
libgtk-x11-2.0.so.0.600.10`_gtk_marshal_BOOLEAN__BOXED+0x79(80969a0, 80473f0, 2, 8047530, 8047418, d1ebc790)
libgobject-2.0.so.0.600.6`g_type_class_meta_marshal+0x42()
libgobject-2.0.so.0.600.6`g_closure_invoke+0xe1()
libgobject-2.0.so.0.600.6`signal_emit_unlocked_R+0x64a()
libgobject-2.0.so.0.600.6`g_signal_emit_valist+0x59d()
libgobject-2.0.so.0.600.6`g_signal_emit+0x23(824aff0, 2b, 0, 81a8650, 80476d8, 80a4ae0)
libgtk-x11-2.0.so.0.600.10`gtk_widget_event_internal+0xf2()
libgtk-x11-2.0.so.0.600.10`gtk_propagate_event+0xc3(824aff0, 81a8650, 8047768, d1f667c3)
libgtk-x11-2.0.so.0.600.10`gtk_main_do_event+0x1b8(81a8650, 0, 80857c0, d1dfa029)
libgdk-x11-2.0.so.0.600.10`gdk_event_dispatch+0x92(8085768, 0, 0, 0)
libglib-2.0.so.0.600.6`g_main_context_dispatch+0x1d5(80857b0, 0, 81a96c8, 7)
libglib-2.0.so.0.600.6`g_main_context_iterate+0x413()
libglib-2.0.so.0.600.6`g_main_loop_run+0x19c()
libgtk-x11-2.0.so.0.600.10`gtk_main+0xa7()
libgncmod-gnome-utils.so.0.0.0`gnc_ui_start_event_loop+0x4e()
inner_main+0x136(0, 1, 8047bf8, d1c25ae4)
libguile.so.12.3.1`scm_boot_guile+0x67(1, 8047bf8, 8051dcc, 0, 1, 8047bf8)
main+0x607(1, 8047bf8, 8047c00)
_start+0x5d()

And here is the cause :

>From "gnucash-2.0.1/src/gnome-utils/dialog-preferences.c" :
void
gnc_preferences_response_cb(GtkDialog *dialog, gint response, GtkDialog *unused)
...
     gnc_gconf_remove_notification(G_OBJECT(dialog), NULL);

If this were the extent of the problem the solution would be simple.
But then I hit the same problem while running gedit :

libc.so.1`_waitid+0xc(4a3, 8047128, 0)
libthread.so.1`waitpid+0x5c()
libgnomeui-2.so.0.400.0`libgnomeui_segv_handle+0x75(b, 0, 804721c)
libthread.so.1`__sighndlr+0xf(b, 0, 804721c, d2e364b0)
libthread.so.1`call_user_handler+0x1c3(b, 0, 804721c)
libthread.so.1`sigacthandler+0x51(b, 0, 804721c)
libglib-2.0.so.0.600.6`_g_gnulib_vasnprintf+0x537()
libglib-2.0.so.0.600.6`_g_gnulib_vasprintf+0x22(80477dc, d2181854, 8047c88, 1)
libglib-2.0.so.0.600.6`g_vasprintf+0x25()
libglib-2.0.so.0.600.6`g_strdup_vprintf+0x29()
libglib-2.0.so.0.600.6`g_logv+0x256()
libglib-2.0.so.0.600.6`g_log+0x23()
libgobject-2.0.so.0.600.6`g_type_check_instance_cast+0x168(80ed520, 80c70b0)
gedit_file_open_uri_list+0xaa(80c4638, 0, 1)
gedit_load_file_list+0x75()
libgtk-x11-2.0.so.0.600.10`gtk_main+0x5d()
main+0x172(2, 8047da8, 8047db4)
_start+0x7a()

> d2181854/s
0xd2181854:     invalid uninstantiatable type `%s' in cast to `%s'

GTypeInstance*
g_type_check_instance_cast (GTypeInstance *type_instance,
			    GType          iface_type)
...
	    g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
		       type_descriptive_name_I (type_instance->g_class->g_type),
		       type_descriptive_name_I (iface_type));

Here the NULL is not hardcoded, so the fix would be a bit more
complex, but the real issue here is the suggestion that there may
be hundreds of these little bugs sprinkled throughout all of those
libraries and applications which depend on glib.

Although Owen may have been correct, it would not be grossly
incorrect to deal with this issue by reimplementing vasnprintf()
in glib to substitute a constant indicator string, e.g. "(nil)", for any
NULL argument to a %s specifier.

What has been the general consensus on this ?


David N. Jafferian
Systems Technology Service Center
Sun Microsystems, Inc.



More information about the gnucash-devel mailing list