SIGSEGV by null pointer dereference in `g_slist_sort->...->g_utf8_collate` after upgrading from 2.76.5 to 2.78.0
When upgrading glib2 Arch Linux package from 2.76.5 to 2.78.0 (there are not versions packaged between that), starting Claws Mail client which uses glib2 causes a segfault in the following stack:
Thread 1 "claws-mail" received signal SIGSEGV, Segmentation fault.
__GI___wcscoll_l (s1=s1@entry=0x0, s2=s2@entry=0x100a94f10 L"encrypted", l=0x7ffff683f3c0 <_nl_global_locale>) at ../string/strcoll_l.c:273
273 if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0'))
(gdb) where
#0 __GI___wcscoll_l (s1=s1@entry=0x0, s2=s2@entry=0x100a94f10 L"encrypted", l=0x7ffff683f3c0 <_nl_global_locale>) at ../string/strcoll_l.c:273
#1 0x00007ffff66b7954 in __GI___wcscoll (s1=s1@entry=0x0, s2=s2@entry=0x100a94f10 L"encrypted") at ../string/strcoll.c:33
#2 0x00007ffff6d0e660 in g_utf8_collate (str1=<optimized out>, str2=<optimized out>) at ../glib/glib/gunicollate.c:122
#3 0x00007ffff6cf2faa in g_slist_sort_merge (user_data=0x0, compare_func=0x100261e00 <summary_tag_cmp_list.lto_priv>, l2=0x100a93a50 = {...}, l1=0x100a93950 = {...}) at ../glib/glib/gslist.c:1005
#4 g_slist_sort_real (list=list@entry=0x100a93950 = {...}, compare_func=compare_func@entry=0x100261e00 <summary_tag_cmp_list.lto_priv>, user_data=user_data@entry=0x0) at ../glib/glib/gslist.c:1047
#5 0x00007ffff6cf2f73 in g_slist_sort_real (list=0x100a93950 = {...}, compare_func=0x100261e00 <summary_tag_cmp_list.lto_priv>, user_data=user_data@entry=0x0) at ../glib/glib/gslist.c:1047
#6 0x00007ffff6cf348b in g_slist_sort (list=<optimized out>, compare_func=<optimized out>) at ../glib/glib/gslist.c:1071
#7 0x000000010035b832 in summary_tags_menu_create.isra.0 (summaryview=summaryview@entry=0x10078db30, refresh=<optimized out>) at /usr/src/debug/claws-mail/claws-mail-4.1.1/src/summaryview.c:6451
#8 0x000000010025f759 in summary_init (summaryview=0x10078db30) at /usr/src/debug/claws-mail/claws-mail-4.1.1/src/summaryview.c:1031
#9 0x00000001001aaf18 in main_window_create () at /usr/src/debug/claws-mail/claws-mail-4.1.1/src/mainwindow.c:2158
#10 0x0000000100123f9b in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/claws-mail/claws-mail-4.1.1/src/main.c:1358
It only depends on glib2 version if we face the error or not, using different Claws Mail versions (neither older ones nor the most recent one from the git master) does not resolve the issue. So, it's highly likely that glib2 is responsible for the issue, not the Claws Mail app.
The error only occurs when Claws Mail already is configured and uses some user date - starting with a clean profile folder is OK. My mails contain many non-ascii characters (from Cyrillic alphabet), I suppose the issue might be related to this.
Some additional info I obtained using a debugger:
-
Here in frame 0 the
s1
pointer isNULL
, and we try to dereference it272 /* Catch empty strings. */ > 273 if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0')) 274 return (*s1 != '\0') - (*s2 != '\0');
-
Here in frame 2 we have pointer
str1_norm
equal toNULL
:119 str1_norm = _g_utf8_normalize_wc (str1, -1, G_NORMALIZE_ALL_COMPOSE); 120 str2_norm = _g_utf8_normalize_wc (str2, -1, G_NORMALIZE_ALL_COMPOSE); 121 > 122 result = wcscoll ((wchar_t *)str1_norm, (wchar_t *)str2_norm);
-
The
str1
from the same frame 2 is notNULL
, but seems to be somehow corrupted:Thread 1 "claws-mail" hit Breakpoint 3, g_utf8_collate (str1=0x1006ebed0 "@", <incomplete sequence \371>, str2=0x1006c1680 "encrypted") at ../glib/glib/gunicollate.c:116 116 g_return_val_if_fail (str1 != NULL, 0); (gdb) print str1 $6 = (const gchar *) 0x1006f78b0 "@", <incomplete sequence \371> (gdb) print *str1 $7 = 64 '@'
And a bunch of bytes from the address pointed by
str1
just in case it might be useful (sorry for such a dummy use of debugger):(gdb) print *((char*)(0x1006f78b0)) $11 = 64 '@' (gdb) print *((char*)(0x1006f78b1)) $12 = 75 'K' (gdb) print *((char*)(0x1006f78b2)) $13 = -7 '\371' (gdb) print *((char*)(0x1006f78b3)) $14 = 0 '\000' (gdb) print *((char*)(0x1006f78b4)) $15 = -1 '\377' (gdb) print *((char*)(0x1006f78b5)) $16 = 127 '\177' (gdb) print *((char*)(0x1006f78b6)) $17 = 0 '\000' (gdb) print *((char*)(0x1006f78b7)) $18 = 0 '\000' (gdb) print *((char*)(0x1006f78b8)) $19 = 48 '0' (gdb) print *((char*)(0x1006f78b9)) $20 = -21 '\353'