aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-08-31 19:00:15 +0000
committerRoland McGrath <roland@gnu.org>2002-08-31 19:00:15 +0000
commit252e798302cd09e68458d2fa8bff0914e6e2ff63 (patch)
tree79cc2df58f580a1f1cf8bdd753c2dfc7e95f40f7
parent605decc1af73e56c10033a74bf4d2641e4c75d89 (diff)
downloadglibc-252e798302cd09e68458d2fa8bff0914e6e2ff63.zip
glibc-252e798302cd09e68458d2fa8bff0914e6e2ff63.tar.gz
glibc-252e798302cd09e68458d2fa8bff0914e6e2ff63.tar.bz2
2002-08-31 Roland McGrath <roland@redhat.com>
* locale/newlocale.c (__newlocale): Don't leak old data or names.
-rw-r--r--locale/newlocale.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/locale/newlocale.c b/locale/newlocale.c
index a016470..ef6f94b 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:
{