GNOME Bugzilla – Bug 142400
gnulib mishandles empty precision
Last modified: 2011-02-18 16:07:29 UTC
I've built the stable branch of GIMP (gimp-2-0) using the current GTK 2.4.1 and GLIB 2.4.1 from Tor Lillqvist, http://www.gimp.org/~tml/gimp/win32/downloads.html It built without problems, but if after some brush strokes, GIMP crashes (see trace below). Note: The crash doesn't happen when LC_ALL is set to C. ----- gimp.exe caused an Access Violation at location 007d5960 in module libglib-2.0-0.dll Reading from location 02a6d000. Registers: eax=00000000 ebx=00000000 ecx=02a6d000 edx=aaaaaab0 esi=0280405b edi=00000002 eip=007d5960 esp=0022f760 ebp=0022fac8 iopl=0 nv up ei pl nz ac po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000216 Call stack: 007D5960 libglib-2.0-0.dll:007D5960 g_win32_get_package_installation_subdirectory 007D5F97 libglib-2.0-0.dll:007D5F97 g_win32_get_package_installation_subdirectory 007CBF5C libglib-2.0-0.dll:007CBF5C g_vasprintf 007945E6 libglib-2.0-0.dll:007945E6 g_strdup_printf 003D6918 libgimpbase-2.0-0.dll:003D6918 gimp_memsize_to_string 004924B9 gimp.exe:004924B9 00491B1C gimp.exe:00491B1C 0077D715 libglib-2.0-0.dll:0077D715 g_idle_remove_by_data 0077DE43 libglib-2.0-0.dll:0077DE43 g_idle_remove_by_data 0077E60B libglib-2.0-0.dll:0077E60B g_idle_remove_by_data 0077A701 libglib-2.0-0.dll:0077A701 g_main_loop_run 00C79F30 libgtk-win32-2.0-0.dll:00C79F30 gtk_main 00401AFA gimp.exe:00401AFA 00402AE5 gimp.exe:00402AE5 0040120D gimp.exe:0040120D 00401238 gimp.exe:00401238 77E614C7 kernel32.dll:77E614C7 GetCurrentDirectoryW
Whoa! Can't reproduce with my default ("sv_FI") locale from Regional Settings, but if I set LANG=de and run gimp-2.0, it indeed crashes. Odd. Will investigate.
The bug is in glib/gnulib/vasnprintf.c. it is not Win32 specific, it should happen on all platforms where the gnulib implementation of vasnprintf gets used. The German GIMP localisation, for some reason, translates the "%.2f MB" string in gimputils.c as "%2.f MB". The vasnprintf() implementation in gnulib doesn't like this kind of format. See the code starting at line 405. When we get here, dp->precision_start points to the ".", and dp->precision_end points to the "f". digitp is set to precision_start+1, i.e. it is initially equal to precision_end. Then a do-while loop is entered, where digitp is incremented each time. As the precision is left out, the loop should not be executed at all, but now it loops until it crashes with a segmentation violation when digitp points outside the process's address space. Should the do-while loop be replaced with a while-do loop?
Created attachment 27658 [details] [review] Suggested patch, fixes crash for me.
Yes that sounds correct, considering what the SUS fprintf specification says: The precision takes the form of a period (.) followed either by an asterisk (*), described below, or an optional decimal digit string, where a null digit string is treated as 0. Please commit to both branches, provided that printf-test still passes with the change. It would also be good to add a testcase involving a null precision to printf-test. Finally, please inform bug-gnulib@gnu.org about the bug and the patch. Thanks.
I've fixed the wrong translations in GIMP (HEAD and stable branch).
Patch committed to HEAD and glib-2-4, and testcases added to printf-test. bug- gnulib informed.