[CentOS-devel] [PATCH] Fix memory leak in i18n support for sort utility

Tue Jan 30 02:01:54 UTC 2018
Yousong Zhou <yszhou4tech at gmail.com>

On 30 January 2018 at 02:58, Kamil Dudka <kdudka at redhat.com> wrote:
> On Wednesday, January 24, 2018 1:18:35 PM CET Yousong Zhou wrote:
>> This can be triggered by using month sort
>>
>> The issue with the original code is that after the call to mbsrtowcs()
>> and wcsrtombs() returns, the source pointer will be set to NULL causing
>> the later free() call has no effect at all
>> ---
>> The issue also exists in c6 branch
>
> Thank you for sharing the patch!  This was tracked as Fedora bug #1259942:
>
> https://bugzilla.redhat.com/1259942
>
> The bug was fixed in coreutils-8.23-11.fc22 and it is going to be fixed
> in the next major version of RHEL (and CentOS).
>
> Kamil

Hi Kamil.  I thought there must exist some kind of mechanism for
backporting bugfixes of this kind into currently maintained versions.
It should!  It's an old bug already known and fixed in 2015 and still
people are wasting time and getting frustrated by it in 2018!

                yousong

>
>>  SOURCES/coreutils-i18n.patch | 45
>> ++++++++++++++++++++++---------------------- 1 file changed, 22
>> insertions(+), 23 deletions(-)
>>
>> diff --git a/SOURCES/coreutils-i18n.patch b/SOURCES/coreutils-i18n.patch
>> index a3c7b33..cdcaffd 100644
>> --- a/SOURCES/coreutils-i18n.patch
>> +++ b/SOURCES/coreutils-i18n.patch
>> @@ -2963,7 +2963,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c line->keybeg = line_start;
>>                       }
>>                   }
>> -@@ -1945,7 +2291,7 @@ human_numcompare (char const *a, char co
>> +@@ -1943,7 +2289,7 @@ human_numcompare (char *a, char *b)
>>      hideously fast. */
>>
>>   static int
>> @@ -2972,7 +2972,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c {
>>     while (blanks[to_uchar (*a)])
>>       a++;
>> -@@ -1955,6 +2301,25 @@ numcompare (char const *a, char const *b
>> +@@ -1953,6 +2299,25 @@ numcompare (char const *a, char const *b
>>     return strnumcmp (a, b, decimal_point, thousands_sep);
>>   }
>>
>> @@ -2998,7 +2998,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c /* Work around a problem whereby the long double
>> value returned by glibc's strtold ("NaN", ...) contains uninitialized bits:
>> clear all bytes of A and B before calling strtold.  FIXME: remove this
>> function once -@@ -2005,7 +2370,7 @@ general_numcompare (char const *sa,
>> char
>> +@@ -2003,7 +2368,7 @@ general_numcompare (char const *sa, char
>>      Return 0 if the name in S is not recognized.  */
>>
>>   static int
>> @@ -3007,7 +3007,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c {
>>     size_t lo = 0;
>>     size_t hi = MONTHS_PER_YEAR;
>> -@@ -2280,15 +2645,14 @@ debug_key (struct line const *line, stru
>> +@@ -2278,15 +2643,14 @@ debug_key (struct line const *line, stru
>>             char saved = *lim;
>>             *lim = '\0';
>>
>> @@ -3025,7 +3025,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c else if (key->general_numeric)
>>               ignore_value (strtold (beg, &tighter_lim));
>>             else if (key->numeric || key->human_numeric)
>> -@@ -2432,7 +2796,7 @@ key_warnings (struct keyfield const *gke
>> +@@ -2430,7 +2794,7 @@ key_warnings (struct keyfield const *gke
>>         bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare
>> (key) && !(key->schar || key->echar); bool line_offset = key->eword == 0 &&
>> key->echar != 0; /* -k1.x,1.y  */ @@ -3034,7 +3034,7 @@ diff -urNp
>> coreutils-8.22-orig/src/sort.c coreutils-8.22/src/sort.c &&
>> ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned))
>>                 || (!key->skipsblanks && key->schar)
>>                 || (!key->skipeblanks && key->echar)))
>>
>> -@@ -2490,11 +2854,87 @@ key_warnings (struct keyfield const *gke
>> +@@ -2488,11 +2852,86 @@ key_warnings (struct keyfield const *gke
>>       error (0, 0, _("option '-r' only applies to last-resort comparison"));
>> }
>>
>> @@ -3047,8 +3047,8 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c +  register int lo = 0, hi = MONTHS_PER_YEAR,
>> result;
>>  +  char *tmp;
>>  +  size_t wclength, mblength;
>> -+  const char **pp;
>> -+  const wchar_t **wpp;
>> ++  const char *pp;
>> ++  const wchar_t *wpp;
>>  +  wchar_t *month_wcs;
>>  +  mbstate_t state;
>>  +
>> @@ -3066,12 +3066,12 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c +  tmp = (char *) xmalloc (len + 1);
>>  +  memcpy (tmp, s, len);
>>  +  tmp[len] = '\0';
>> -+  pp = (const char **)&tmp;
>>  +  month_wcs = (wchar_t *) xmalloc ((len + 1) * sizeof (wchar_t));
>>  +  memset (&state, '\0', sizeof(mbstate_t));
>>  +
>> -+  wclength = mbsrtowcs (month_wcs, pp, len + 1, &state);
>> -+  if (wclength == (size_t)-1 || *pp != NULL)
>> ++  pp = tmp;
>> ++  wclength = mbsrtowcs (month_wcs, &pp, len + 1, &state);
>> ++  if (wclength == (size_t)-1 || pp != NULL)
>>  +    error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s));
>>  +
>>  +  for (i = 0; i < wclength; i++)
>> @@ -3084,10 +3084,9 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c +        }
>>  +    }
>>  +
>> -+  wpp = (const wchar_t **)&month_wcs;
>> -+
>> -+  mblength = wcsrtombs (month, wpp, len + 1, &state);
>> -+  assert (mblength != (-1) && *wpp == NULL);
>> ++  wpp = month_wcs;
>> ++  mblength = wcsrtombs (month, &wpp, len + 1, &state);
>> ++  assert (mblength != (-1) && wpp == NULL);
>>  +
>>  +  do
>>  +    {
>> @@ -3123,7 +3122,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c {
>>     struct keyfield *key = keylist;
>>
>> -@@ -2579,7 +3019,7 @@ keycompare (struct line const *a, struct
>> +@@ -2577,7 +3016,7 @@ keycompare (struct line const *a, struct
>>             else if (key->human_numeric)
>>               diff = human_numcompare (ta, tb);
>>             else if (key->month)
>> @@ -3132,7 +3131,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c else if (key->random)
>>               diff = compare_random (ta, tlena, tb, tlenb);
>>             else if (key->version)
>> -@@ -2695,6 +3135,209 @@ keycompare (struct line const *a, struct
>> +@@ -2693,6 +3132,209 @@ keycompare (struct line const *a, struct
>>     return key->reverse ? -diff : diff;
>>   }
>>
>> @@ -3342,7 +3341,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c /* Compare two lines A and B, returning negative,
>> zero, or positive depending on whether A compares less than, equal to, or
>> greater than B. */
>>
>> -@@ -2722,7 +3365,7 @@ compare (struct line const *a, struct li
>> +@@ -2720,7 +3362,7 @@ compare (struct line const *a, struct li
>>       diff = - NONZERO (blen);
>>     else if (blen == 0)
>>       diff = 1;
>> @@ -3351,7 +3350,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c {
>>         /* Note xmemcoll0 is a performance enhancement as
>>            it will not unconditionally write '\0' after the
>> -@@ -4113,6 +4756,7 @@ set_ordering (char const *s, struct keyf
>> +@@ -4111,6 +4753,7 @@ set_ordering (char const *s, struct keyf
>>             break;
>>           case 'f':
>>             key->translate = fold_toupper;
>> @@ -3359,7 +3358,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c break;
>>           case 'g':
>>             key->general_numeric = true;
>> -@@ -4190,7 +4834,7 @@ main (int argc, char **argv)
>> +@@ -4188,7 +4831,7 @@ main (int argc, char **argv)
>>     initialize_exit_failure (SORT_FAILURE);
>>
>>     hard_LC_COLLATE = hard_locale (LC_COLLATE);
>> @@ -3368,7 +3367,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c hard_LC_TIME = hard_locale (LC_TIME);
>>   #endif
>>
>> -@@ -4211,6 +4855,29 @@ main (int argc, char **argv)
>> +@@ -4209,6 +4852,29 @@ main (int argc, char **argv)
>>         thousands_sep = -1;
>>     }
>>
>> @@ -3398,7 +3397,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c have_read_stdin = false;
>>     inittables ();
>>
>> -@@ -4485,13 +5152,34 @@ main (int argc, char **argv)
>> +@@ -4483,13 +5149,34 @@ main (int argc, char **argv)
>>
>>           case 't':
>>             {
>> @@ -3437,7 +3436,7 @@ diff -urNp coreutils-8.22-orig/src/sort.c
>> coreutils-8.22/src/sort.c else
>>                     {
>>                       /* Provoke with 'sort -txx'.  Complain about
>> -@@ -4502,9 +5190,12 @@ main (int argc, char **argv)
>> +@@ -4500,9 +5187,12 @@ main (int argc, char **argv)
>>                              quote (optarg));
>>                     }
>>                 }