about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2014-05-28 14:41:52 +0200
committerAllan McRae <allan@archlinux.org>2014-09-05 22:44:10 +1000
commit2da15d05c54738ed2c53aaf555c7cf51a9057844 (patch)
treeb8671cbcddb091a5060f7058828a88c12ae24b19
parent6ccc1c41f52f93548b5eb64d106219e287052472 (diff)
downloadglibc-2da15d05c54738ed2c53aaf555c7cf51a9057844.tar.gz
glibc-2da15d05c54738ed2c53aaf555c7cf51a9057844.tar.xz
glibc-2da15d05c54738ed2c53aaf555c7cf51a9057844.zip
setlocale: Use the heap for the copy of the locale argument
This avoids alloca calls with potentially large arguments.

(cherry picked from commit d183645616b0533b3acee28f1a95570bffbdf50f)
-rw-r--r--ChangeLog5
-rw-r--r--locale/setlocale.c14
2 files changed, 17 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 0255114fba..38efe3d650 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-07-02  Florian Weimer  <fweimer@redhat.com>
+
+	* locale/setlocale.c (setlocale): Use strdup for allocating
+	composite name copy.
+
 2014-05-26  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #16878]
diff --git a/locale/setlocale.c b/locale/setlocale.c
index b70fa6cbce..a4c59832ca 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -272,6 +272,8 @@ setlocale (int category, const char *locale)
 	 of entries of the form `CATEGORY=VALUE'.  */
       const char *newnames[__LC_LAST];
       struct __locale_data *newdata[__LC_LAST];
+      /* Copy of the locale argument, for in-place splitting.  */
+      char *locale_copy = NULL;
 
       /* Set all name pointers to the argument name.  */
       for (category = 0; category < __LC_LAST; ++category)
@@ -281,7 +283,13 @@ setlocale (int category, const char *locale)
       if (__builtin_expect (strchr (locale, ';') != NULL, 0))
 	{
 	  /* This is a composite name.  Make a copy and split it up.  */
-	  char *np = strdupa (locale);
+	  locale_copy = strdup (locale);
+	  if (__glibc_unlikely (locale_copy == NULL))
+	    {
+	      __libc_rwlock_unlock (__libc_setlocale_lock);
+	      return NULL;
+	    }
+	  char *np = locale_copy;
 	  char *cp;
 	  int cnt;
 
@@ -299,6 +307,7 @@ setlocale (int category, const char *locale)
 		{
 		error_return:
 		  __libc_rwlock_unlock (__libc_setlocale_lock);
+		  free (locale_copy);
 
 		  /* Bogus category name.  */
 		  ERROR_RETURN;
@@ -391,8 +400,9 @@ setlocale (int category, const char *locale)
       /* Critical section left.  */
       __libc_rwlock_unlock (__libc_setlocale_lock);
 
-      /* Free the resources (the locale path variable).  */
+      /* Free the resources.  */
       free (locale_path);
+      free (locale_copy);
 
       return composite;
     }