clone 310588 -1 reassign -1 libc6 tags -1 + patch thanks On Tue, May 24, 2005 at 03:57:48PM +0300, Eugeniy Meshcheryakov wrote: > Package: belocs-locales-bin > Version: 2.3.4-8 > Severity: important > > Some programs segfault when run with belocs-locales-* packages > installed. Examples include: gimp when run with Ukrainian locale (also > Russian, Serbian, Japanese and others), mozilla-firefox with > mozilla-firefox-locale-uk (crashes after selecting some menu entries), > sort (see attached script, crashes when run in UTF-8 locale). These > programs do not crash with locales package installed.
Many thanks to Eugeniy who spent hours during last week to help me understand what's going wrong here. The conclusion is that there is a bug in strxfrm_l.c. I just filed BZ#968 upstream. The proposed patch is quite trivial, but I could not test it. It can be reviewed without knowing strxfrm_l.c internals, the issue is that the variable in a decremental loop is unsigned and checked by backw >= backw_stop whereas backw_stop may be 0. I would be glad if you glibc guys could review and apply this patch. Thanks Denis
Index: string/strxfrm_l.c =================================================================== RCS file: /cvs/glibc/libc/string/strxfrm_l.c,v retrieving revision 1.4 diff -u -r1.4 strxfrm_l.c --- string/strxfrm_l.c 14 Mar 2004 20:52:47 -0000 1.4 +++ string/strxfrm_l.c 23 May 2005 22:35:59 -0000 @@ -210,18 +210,19 @@ /* Handle the pushed elements now. */ size_t backw; - for (backw = idxcnt - 1; backw >= backw_stop; --backw) + /* Take care of integer overflow if backw_stop is 0. */ + for (backw = idxcnt; backw > backw_stop; --backw) { - len = weights[idxarr[backw]++]; + len = weights[idxarr[backw - 1]++]; if (needed + len < n) while (len-- > 0) - dest[needed++] = weights[idxarr[backw]++]; + dest[needed++] = weights[idxarr[backw - 1]++]; else { /* No more characters fit into the buffer. */ needed += len; - idxarr[backw] += len; + idxarr[backw - 1] += len; } } @@ -293,9 +294,10 @@ /* Handle the pushed elements now. */ size_t backw; - for (backw = idxcnt - 1; backw >= backw_stop; --backw) + /* Take care of integer overflow if backw_stop is 0. */ + for (backw = idxcnt; backw > backw_stop; --backw) { - len = weights[idxarr[backw]++]; + len = weights[idxarr[backw - 1]++]; if (len != 0) { #ifdef WIDE_CHAR_VERSION @@ -304,7 +306,7 @@ dest[needed] = val; for (i = 0; i < len; ++i) dest[needed + 1 + i] = - weights[idxarr[backw] + i]; + weights[idxarr[backw - 1] + i]; } needed += 1 + len; #else @@ -315,11 +317,11 @@ dest[needed + i] = buf[i]; for (i = 0; i < len; ++i) dest[needed + buflen + i] = - weights[idxarr[backw] + i]; + weights[idxarr[backw - 1] + i]; } needed += buflen + len; #endif - idxarr[backw] += len; + idxarr[backw - 1] += len; val = 1; } else