]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix BZ #19012 -- iconv_open leaks memory on error path.
authorPaul Pluzhnikov <ppluzhnikov@google.com>
Tue, 6 Oct 2015 03:03:48 +0000 (20:03 -0700)
committerPaul Pluzhnikov <ppluzhnikov@google.com>
Tue, 6 Oct 2015 03:03:48 +0000 (20:03 -0700)
ChangeLog
NEWS
iconv/gconv_db.c

index 77d065202e95b297d67dc3afc60954c2336e3370..259b05e692c9b78612ad212f7d42b48415355a33 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-10-05  Paul Pluzhnikov  <ppluzhnikov@google.com>
+
+       [BZ #19012]
+       * iconv/gconv_db.c (gen_steps): Check for additional errors.
+       Clean up on failure.
+
 2015-10-05  Joseph Myers  <joseph@codesourcery.com>
 
        [BZ #19071]
diff --git a/NEWS b/NEWS
index d14efbd9e0b2cc2139c8db7ffe83a8d82b3a4df5..16f5cfb00288d286a8fddb05cbfbb7e40d5c06a1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,8 +17,8 @@ Version 2.23
   18757, 18778, 18781, 18787, 18789, 18790, 18795, 18796, 18803, 18820,
   18823, 18824, 18825, 18857, 18863, 18870, 18872, 18873, 18875, 18887,
   18921, 18951, 18952, 18956, 18961, 18966, 18967, 18969, 18970, 18977,
-  18980, 18981, 18985, 19003, 19016, 19032, 19046, 19049, 19050, 19059,
-  19071.
+  18980, 18981, 18985, 19003, 19012, 19016, 19032, 19046, 19049, 19050,
+  19059, 19071.
 
 * The obsolete header <regexp.h> has been removed.  Programs that require
   this header must be updated to use <regex.h> instead.
index 4e6ec657e2a7307858c85ca55aad707170ef031c..74b4ff5670d0061e8c290140a44ef1169482d0a8 100644 (file)
@@ -243,6 +243,8 @@ gen_steps (struct derivation_step *best, const char *toset,
   struct __gconv_step *result;
   struct derivation_step *current;
   int status = __GCONV_NOMEM;
+  char *from_name = NULL;
+  char *to_name = NULL;
 
   /* First determine number of steps.  */
   for (current = best; current->last != NULL; current = current->last)
@@ -259,12 +261,30 @@ gen_steps (struct derivation_step *best, const char *toset,
       current = best;
       while (step_cnt-- > 0)
        {
-         result[step_cnt].__from_name = (step_cnt == 0
-                                         ? __strdup (fromset)
-                                         : (char *)current->last->result_set);
-         result[step_cnt].__to_name = (step_cnt + 1 == *nsteps
-                                       ? __strdup (current->result_set)
-                                       : result[step_cnt + 1].__from_name);
+         if (step_cnt == 0)
+           {
+             result[step_cnt].__from_name = from_name = __strdup (fromset);
+             if (from_name == NULL)
+               {
+                 failed = 1;
+                 break;
+               }
+           }
+         else
+           result[step_cnt].__from_name = (char *)current->last->result_set;
+
+         if (step_cnt + 1 == *nsteps)
+           {
+             result[step_cnt].__to_name = to_name
+               = __strdup (current->result_set);
+             if (to_name == NULL)
+               {
+                 failed = 1;
+                 break;
+               }
+           }
+         else
+           result[step_cnt].__to_name = result[step_cnt + 1].__from_name;
 
          result[step_cnt].__counter = 1;
          result[step_cnt].__data = NULL;
@@ -332,6 +352,8 @@ gen_steps (struct derivation_step *best, const char *toset,
          while (++step_cnt < *nsteps)
            __gconv_release_step (&result[step_cnt]);
          free (result);
+         free (from_name);
+         free (to_name);
          *nsteps = 0;
          *handle = NULL;
          if (status == __GCONV_OK)
@@ -828,8 +850,9 @@ free_modules_db (struct gconv_module *node)
 /* Free all resources if necessary.  */
 libc_freeres_fn (free_mem)
 {
-  /* First free locale memory.  This needs to be done before freeing derivations,
-     as ctype cleanup functions dereference steps arrays which we free below.  */
+  /* First free locale memory.  This needs to be done before freeing
+     derivations, as ctype cleanup functions dereference steps arrays which we
+     free below.  */
   _nl_locale_subfreeres ();
 
   /* finddomain.c has similar problem.  */