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);