From: Paul Pluzhnikov Date: Tue, 6 Oct 2015 03:03:48 +0000 (-0700) Subject: Fix BZ #19012 -- iconv_open leaks memory on error path. X-Git-Tag: glibc-2.23~405 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be64c2ef2ac2357ddff61841f2cc8246e5da1b20;p=thirdparty%2Fglibc.git Fix BZ #19012 -- iconv_open leaks memory on error path. --- diff --git a/ChangeLog b/ChangeLog index 77d065202e9..259b05e692c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-05 Paul Pluzhnikov + + [BZ #19012] + * iconv/gconv_db.c (gen_steps): Check for additional errors. + Clean up on failure. + 2015-10-05 Joseph Myers [BZ #19071] diff --git a/NEWS b/NEWS index d14efbd9e0b..16f5cfb0028 100644 --- 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 has been removed. Programs that require this header must be updated to use instead. diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c index 4e6ec657e2a..74b4ff5670d 100644 --- a/iconv/gconv_db.c +++ b/iconv/gconv_db.c @@ -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. */