Hi Stefan, hi Vincent,

after I could successfully reproduce the crash here with gnucash 1:2.4.6-3, I
digged around a little bit in the core dump (see also my attached full
backtrace). Things seem to go wrong somewhere in the callback function
gtk_entry_completion_default_completion_func():

---  gtk/gtkentrycompletion.c, line 765ff. -----

static gboolean
gtk_entry_completion_default_completion_func (GtkEntryCompletion *completion,
                                              const gchar        *key,
                                              GtkTreeIter        *iter,
                                              gpointer            user_data)
{
  gchar *item = NULL;
  gchar *normalized_string;
  gchar *case_normalized_string;

  [...]

  if (item != NULL)
    {
      normalized_string = g_utf8_normalize (item, -1, G_NORMALIZE_ALL);
      case_normalized_string = g_utf8_casefold (normalized_string, -1);

      if (!strncmp (key, case_normalized_string, strlen (key)))
        ret = TRUE;

      g_free (item);
      g_free (normalized_string);
      g_free (case_normalized_string);
    }

  return ret;
}

------------------------------------------------

With gdb I figured out that when strncmp() is called, case_normalized_string is
a NULL pointer. This was returned by g_utf8_casefold(), probably because its
first parameter 'normalized_string' already was a NULL pointer (ie.
g_utf8_casefold() handles NULL pointers gracefully). This in turn means
that the NULL pointer was already returned by g_utf8_normalize(). Reading the
GLib Reference Manual this is a perfectly valid return value (meaning the input
string was no valid UTF-8), which the calling code must be prepared to get
returned.

To fix the segfault, case_normalized_string should be checked for NULL.
strncmp() should then only be called if it isn't NULL. The attached patch
changes the code accordingly. I built the Gtk libraries with the patch applied
and can confirm that it fixes the Gnucash crash.

As this is no issue in Gnucash but in Gtk, I am going to re-assign this bug to
the gtk+2.0 package now.

Regards,
Micha
Program received signal SIGSEGV, Segmentation fault.
__strncmp_ssse3 () at ../sysdeps/i386/i686/multiarch/strcmp-ssse3.S:2064
2064    ../sysdeps/i386/i686/multiarch/strcmp-ssse3.S: Datei oder Verzeichnis 
nicht gefunden.
        in ../sysdeps/i386/i686/multiarch/strcmp-ssse3.S
(gdb) bt full
#0  __strncmp_ssse3 () at ../sysdeps/i386/i686/multiarch/strcmp-ssse3.S:2064
No locals.
#1  0xb74ec13e in gtk_entry_completion_default_completion_func 
(model=0x840f090, iter=0xbfffef50, data=0x83a3970)
    at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtkentrycompletion.c:793
        normalized_string = 0x0
        case_normalized_string = 0x0
        ret = 0
        model = <value optimized out>
        item = 0x84e64a8 "ANG (Niederl\344ndische Antillen-Gulden)"
#2  gtk_entry_completion_visible_func (model=0x840f090, iter=0xbfffef50, 
data=0x83a3970)
    at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtkentrycompletion.c:822
        ret = 0
        completion = 0x83a3970
#3  0xb7654fc7 in gtk_tree_model_filter_visible (filter=<value optimized out>, 
child_iter=<value optimized out>)
    at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtktreemodelfilter.c:764
No locals.
#4  0xb7659677 in gtk_tree_model_filter_row_changed (c_model=0x840f090, 
c_path=0x84db5d8, c_iter=0xbffff020, data=0x83a3b30)
    at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtktreemodelfilter.c:1253
        filter = 0x83a3b30
        iter = {stamp = -1216337424, user_data = 0x840f090, user_data2 = 
0xbfffefb8, user_data3 = 0xb7653386}
        children = {stamp = 137309776, user_data = 0x0, user_data2 = 
0xbfffefa8, user_data3 = 0xb78029f0}
        real_c_iter = {stamp = -1896328952, user_data = 0x82f2e50, user_data2 = 
0x0, user_data3 = 0x0}
        path = 0x0
        elt = <value optimized out>
        level = <value optimized out>
        requested_state = <value optimized out>
        current_state = <value optimized out>
        free_c_path = 0
        signals_emitted = 0
        __PRETTY_FUNCTION__ = "gtk_tree_model_filter_row_changed"
#5  0xb76599f6 in gtk_tree_model_filter_refilter_helper (model=0x840f090, 
path=0x84db5d8, iter=0xbffff020, data=0x83a3b30)
    at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtktreemodelfilter.c:3457
No locals.
#6  0xb76534e0 in gtk_tree_model_foreach_helper (model=0x840f090, 
iter=0xbffff020, path=0x84db5d8, func=0xb76599d0 
<gtk_tree_model_filter_refilter_helper>, 
    user_data=0x83a3b30) at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtktreemodel.c:1607
        child = {stamp = 0, user_data = 0x0, user_data2 = 0x0, user_data3 = 0x0}
#7  0xb765479b in IA__gtk_tree_model_foreach (model=0x840f090, func=0xb76599d0 
<gtk_tree_model_filter_refilter_helper>, user_data=0x83a3b30)
    at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtktreemodel.c:1653
        path = 0x84db5d8
        iter = {stamp = -1896328952, user_data = 0x82f2e50, user_data2 = 0x0, 
user_data3 = 0x0}
        __PRETTY_FUNCTION__ = "IA__gtk_tree_model_foreach"
#8  0xb7658f8c in IA__gtk_tree_model_filter_refilter (filter=0x83a3b30) at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtktreemodelfilter.c:3477
        __PRETTY_FUNCTION__ = "IA__gtk_tree_model_filter_refilter"
#9  0xb74ed566 in IA__gtk_entry_completion_complete (completion=0x83a3970) at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtkentrycompletion.c:1182
        tmp = 0x84e16b0 "\a"
        __PRETTY_FUNCTION__ = "IA__gtk_entry_completion_complete"
#10 0xb74d9d9c in check_completion_callback (completion=0x83a3970) at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtkentry.c:9651
No locals.
#11 0xb7045f1c in source_closure_marshal_BOOLEAN__VOID (closure=0x84b6138, 
return_value=0xbffff19c, n_param_values=0, param_values=0x0, 
invocation_hint=0x0, 
    marshal_data=0x0) at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./gobject/gsourceclosure.c:71
        callback = <value optimized out>
        cc = 0x84b6138
        v_return = <value optimized out>
        __PRETTY_FUNCTION__ = "source_closure_marshal_BOOLEAN__VOID"
#12 0xb70289f2 in g_closure_invoke (closure=0x84b6138, return_value=0xbffff19c, 
n_param_values=0, param_values=0x0, invocation_hint=0x0)
    at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./gobject/gclosure.c:767
        marshal = 0xb7045ec0 <source_closure_marshal_BOOLEAN__VOID>
        marshal_data = 0x0
        in_marshal = -1073745664
        __PRETTY_FUNCTION__ = "g_closure_invoke"
#13 0xb7045fb7 in source_closure_callback (data=0x84b6138) at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./gobject/gsourceclosure.c:113
        closure = 0x84b6138
        result_value = {g_type = 20, data = {{v_int = 0, v_uint = 0, v_long = 
0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer 
= 0x0}, {
              v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, 
v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}}
        result = <value optimized out>
#14 0xb6f6da41 in g_idle_dispatch (source=0x849d880, callback=0xb7045f40 
<source_closure_callback>, user_data=0x84b6138)
    at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./glib/gmain.c:4545
No locals.
#15 0xb6f72252 in g_main_dispatch (context=0x8085e68) at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./glib/gmain.c:2440
        dispatch = 0xb6f6da20 <g_idle_dispatch>
        was_in_call = 0
        user_data = 0x84b6138
        callback = 0xb7045f40 <source_closure_callback>
        cb_funcs = 0xb7063300
        cb_data = 0x84b6138
        current_source_link = {data = 0x849d880, next = 0x0}
        need_destroy = <value optimized out>
        source = 0x849d880
        current = 0x809a690
        i = <value optimized out>
#16 g_main_context_dispatch (context=0x8085e68) at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./glib/gmain.c:3013
No locals.
#17 0xb6f72a30 in g_main_context_iterate (context=0x8085e68, block=1, 
dispatch=1, self=<value optimized out>)
    at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./glib/gmain.c:3091
        max_priority = -100
        timeout = 0
        some_ready = 1
        nfds = <value optimized out>
        allocated_nfds = <value optimized out>
        fds = 0x811c590
#18 0xb6f730f3 in g_main_loop_run (loop=0x81d2f30) at 
/build/buildd-glib2.0_2.28.6-1-i386-A3fp41/glib2.0-2.28.6/./glib/gmain.c:3299
        __PRETTY_FUNCTION__ = "g_main_loop_run"
#19 0xb755ebd9 in IA__gtk_main () at 
/build/buildd-gtk+2.0_2.24.4-3-i386-ouUeDk/gtk+2.0-2.24.4/gtk/gtkmain.c:1256
        tmp_list = <value optimized out>
        functions = 0x0
        init = <value optimized out>
        loop = 0x81d2f30
#20 0xb7ec3894 in gnc_ui_start_event_loop () at gnc-gnome-utils.c:668
        id = 471
#21 0x0804d4d4 in inner_main (closure=0x0, argc=1, argv=0xbffff774) at 
gnucash-bin.c:735
        main_mod = 0xb30621d0
        fn = 0x82fb9b8 ""
        error = 0x0
#22 0xb7bf6416 in ?? () from /usr/lib/libguile.so.17
No symbol table info available.
#23 0xb7bc8022 in ?? () from /usr/lib/libguile.so.17
No symbol table info available.
#24 0xb7c3d518 in scm_c_catch () from /usr/lib/libguile.so.17
No symbol table info available.
#25 0xb7bc8657 in scm_i_with_continuation_barrier () from 
/usr/lib/libguile.so.17
No symbol table info available.
#26 0xb7bc8733 in scm_c_with_continuation_barrier () from 
/usr/lib/libguile.so.17
No symbol table info available.
#27 0xb7c3bd99 in scm_i_with_guile_and_parent () from /usr/lib/libguile.so.17
No symbol table info available.
#28 0xb7c3bdee in scm_with_guile () from /usr/lib/libguile.so.17
No symbol table info available.
#29 0xb7bf64ff in scm_boot_guile () from /usr/lib/libguile.so.17
No symbol table info available.
#30 0x0804d8b1 in main (argc=1, argv=0xbffff774) at gnucash-bin.c:879
No locals.
(gdb) 
--- gtk+2.0-2.24.4.orig/gtk/gtkentrycompletion.c
+++ gtk+2.0-2.24.4/gtk/gtkentrycompletion.c
@@ -790,7 +790,8 @@ gtk_entry_completion_default_completion_
       normalized_string = g_utf8_normalize (item, -1, G_NORMALIZE_ALL);
       case_normalized_string = g_utf8_casefold (normalized_string, -1);
       
-      if (!strncmp (key, case_normalized_string, strlen (key)))
+      if ((case_normalized_string != NULL) &&
+          !strncmp (key, case_normalized_string, strlen (key)))
 	ret = TRUE;
       
       g_free (item);

Reply via email to