]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
duplocale: protect use of global locale (bug 23970)
authorAndreas Schwab <schwab@suse.de>
Wed, 6 Mar 2024 11:59:47 +0000 (12:59 +0100)
committerAndreas Schwab <schwab@suse.de>
Mon, 11 Mar 2024 08:52:59 +0000 (09:52 +0100)
Protect the global locale from being modified while we compute the size of
the locale category names.  That allows the use of the global locale in a
single thread, while all other threads use the thread safe locale
functions.

locale/duplocale.c

index a755ac5c362a8e4dc953b3c2b5efa3151654aab4..bad476700f0b3893145eb171682c73765d7bd7cd 100644 (file)
@@ -43,6 +43,11 @@ __duplocale (locale_t dataset)
   int cnt;
   size_t names_len = 0;
 
+  /* If dataset points to _nl_global_locale, we need to prevent other
+     threads from modifying it.  We also modify global data below (the
+     usage counts).  */
+  __libc_rwlock_wrlock (__libc_setlocale_lock);
+
   /* Calculate the total space we need to store all the names.  */
   for (cnt = 0; cnt < __LC_LAST; ++cnt)
     if (cnt != LC_ALL && dataset->__names[cnt] != _nl_C_name)
@@ -55,9 +60,6 @@ __duplocale (locale_t dataset)
     {
       char *namep = (char *) (result + 1);
 
-      /* We modify global data (the usage counts).  */
-      __libc_rwlock_wrlock (__libc_setlocale_lock);
-
       for (cnt = 0; cnt < __LC_LAST; ++cnt)
        if (cnt != LC_ALL)
          {
@@ -78,11 +80,11 @@ __duplocale (locale_t dataset)
       result->__ctype_b = dataset->__ctype_b;
       result->__ctype_tolower = dataset->__ctype_tolower;
       result->__ctype_toupper = dataset->__ctype_toupper;
-
-      /* It's done.  */
-      __libc_rwlock_unlock (__libc_setlocale_lock);
     }
 
+  /* It's done.  */
+  __libc_rwlock_unlock (__libc_setlocale_lock);
+
   return result;
 }
 weak_alias (__duplocale, duplocale)