about summary refs log tree commit diff
path: root/locale/duplocale.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/duplocale.c')
-rw-r--r--locale/duplocale.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/locale/duplocale.c b/locale/duplocale.c
index f8e8e7299e..df856a2a83 100644
--- a/locale/duplocale.c
+++ b/locale/duplocale.c
@@ -33,15 +33,39 @@ __locale_t
 __duplocale (__locale_t dataset)
 {
   __locale_t result;
+  int cnt;
 
   /* We modify global data.  */
   __libc_lock_lock (__libc_setlocale_lock);
 
   /* Get memory.  */
   result = (__locale_t) malloc (sizeof (struct __locale_struct));
+
+  if (result != NULL)
+    /* Duplicate the names in a separate loop first so we can
+       bail out if strdup fails and not have touched usage_counts.  */
+    for (cnt = 0; cnt < __LC_LAST; ++cnt)
+      if (cnt != LC_ALL)
+	{
+	  if (dataset->__names[cnt] == _nl_C_name)
+	    result->__names[cnt] = _nl_C_name;
+	  else
+	    {
+	      result->__names[cnt] = __strdup (dataset->__names[cnt]);
+	      if (result->__names[cnt] == NULL)
+		{
+		  while (cnt-- > 0)
+		    if (dataset->__names[cnt] != _nl_C_name)
+		      free ((char *) dataset->__names[cnt]);
+		  free (result);
+		  result = NULL;
+		  break;
+		}
+	    }
+	}
+
   if (result != NULL)
     {
-      int cnt;
       for (cnt = 0; cnt < __LC_LAST; ++cnt)
 	if (cnt != LC_ALL)
 	  {