diff options
author | Roland McGrath <roland@gnu.org> | 2002-08-31 19:00:15 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-08-31 19:00:15 +0000 |
commit | 252e798302cd09e68458d2fa8bff0914e6e2ff63 (patch) | |
tree | 79cc2df58f580a1f1cf8bdd753c2dfc7e95f40f7 /locale/newlocale.c | |
parent | 605decc1af73e56c10033a74bf4d2641e4c75d89 (diff) | |
download | glibc-252e798302cd09e68458d2fa8bff0914e6e2ff63.tar.gz glibc-252e798302cd09e68458d2fa8bff0914e6e2ff63.tar.xz glibc-252e798302cd09e68458d2fa8bff0914e6e2ff63.zip |
2002-08-31 Roland McGrath <roland@redhat.com>
* locale/newlocale.c (__newlocale): Don't leak old data or names.
Diffstat (limited to 'locale/newlocale.c')
-rw-r--r-- | locale/newlocale.c | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/locale/newlocale.c b/locale/newlocale.c index a016470fcf..ef6f94befb 100644 --- a/locale/newlocale.c +++ b/locale/newlocale.c @@ -144,14 +144,16 @@ __newlocale (int category_mask, const char *locale, __locale_t base) /* Now process all categories we are interested in. */ for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL && (category_mask & 1 << cnt) != 0) + if ((category_mask & 1 << cnt) != 0) { result.__locales[cnt] = _nl_find_locale (locale_path, locale_path_len, cnt, &newnames[cnt]); if (result.__locales[cnt] == NULL) { + free_data_and_exit: while (cnt-- > 0) - if (result.__locales[cnt]->usage_count != UNDELETABLE) + if (((category_mask & 1 << cnt) != 0) + && result.__locales[cnt]->usage_count != UNDELETABLE) /* We can remove the data. */ _nl_remove_locale (cnt, result.__locales[cnt]); return NULL; @@ -164,24 +166,25 @@ __newlocale (int category_mask, const char *locale, __locale_t base) /* Allocate new structure. */ result_ptr = (__locale_t) malloc (sizeof (struct __locale_struct)); if (result_ptr == NULL) - return NULL; + goto free_data_and_exit; - /* Install strdup'd names in the new structure's __names array. */ + /* Install strdup'd names in the new structure's __names array. + If resolved to "C", that is already in RESULT.__names to start. */ for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL && result.__names[cnt] != _nl_C_name) + if ((category_mask & 1 << cnt) != 0 && newnames[cnt] != _nl_C_name) { - result.__names[cnt] = __strdup (((category_mask & 1 << cnt) != 0) - ? newnames[cnt] - : result.__names[cnt]); + result.__names[cnt] = __strdup (newnames[cnt]); if (result.__names[cnt] == NULL) { + free (result_ptr); while (cnt-- > 0) if (result.__names[cnt] != _nl_C_name) free ((char *) result.__names[cnt]); - free (result_ptr); - return NULL; + goto free_data_and_exit; } } + + *result_ptr = result; } else { @@ -189,35 +192,36 @@ __newlocale (int category_mask, const char *locale, __locale_t base) First strdup the names we were given for the new locale. */ for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL && ((category_mask & 1 << cnt) != 0) - && result.__names[cnt] != _nl_C_name) + if ((category_mask & 1 << cnt) != 0 && newnames[cnt] != _nl_C_name) { newnames[cnt] = __strdup (newnames[cnt]); if (newnames[cnt] == NULL) { while (cnt-- > 0) - if (newnames[cnt] != NULL) + if ((category_mask & 1 << cnt) != 0 && + newnames[cnt] != _nl_C_name) free ((char *) newnames[cnt]); - return NULL; + goto free_data_and_exit; } } - else - newnames[cnt] = NULL; - /* Now that we can't lose, install the new names. */ + /* Now that we can't lose, install the new data. */ for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (newnames[cnt] != NULL) + if ((category_mask & 1 << cnt) != 0) { - if (result.__names[cnt] != _nl_C_name) - free ((char *) result.__names[cnt]); - result.__names[cnt] = __strdup (newnames[cnt]); + if (base->__locales[cnt]->usage_count != UNDELETABLE) + /* We can remove the old data. */ + _nl_remove_locale (cnt, base->__locales[cnt]); + base->__locales[cnt] = result.__locales[cnt]; + + if (base->__names[cnt] != _nl_C_name) + free ((char *) base->__names[cnt]); + base->__names[cnt] = newnames[cnt]; } result_ptr = base; } - *result_ptr = result; - /* Update the special members. */ update: { |