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

Wed Jan 24 12:18:35 UTC 2018
Yousong Zhou <yszhou4tech at gmail.com>

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

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