bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

duplocale: fix multithread-safety bug on AIX


From: Bruno Haible
Subject: duplocale: fix multithread-safety bug on AIX
Date: Sun, 15 Dec 2019 23:47:58 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-166-generic; KDE/5.18.0; x86_64; ; )

The first application of the 'setlocale-null' module is to fix the duplocale()
replacement.


2019-12-15  Bruno Haible  <address@hidden>

        duplocale: Fix multithread-safety bug on AIX.
        * lib/duplocale.c: Don't include <stdlib.h>.
        (rpl_duplocale): Invoke setlocale_null instead of setlocale.
        * m4/duplocale.m4 (gl_FUNC_DUPLOCALE): Require gl_FUNC_SETLOCALE_NULL.
        Set LIB_DUPLOCALE.
        * modules/duplocale (Depends-on): Add setlocale-null.
        (Link): New section.
        * modules/duplocale-tests (Makefile.am): Link test-duplocale with
        $(LIB_DUPLOCALE).

diff --git a/lib/duplocale.c b/lib/duplocale.c
index 3b958ba..d22a447 100644
--- a/lib/duplocale.c
+++ b/lib/duplocale.c
@@ -22,7 +22,6 @@
 #include <locale.h>
 
 #include <errno.h>
-#include <stdlib.h>
 #include <string.h>
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
@@ -68,27 +67,33 @@ rpl_duplocale (locale_t locale)
           , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK }
 #endif
         };
-      char *base_name;
+      char base_name[SETLOCALE_NULL_MAX];
+      int err;
       locale_t base_copy;
       unsigned int i;
 
-      base_name = strdup (setlocale (LC_CTYPE, NULL));
-      if (base_name == NULL)
-        return NULL;
-      base_copy = newlocale (LC_ALL_MASK, base_name, NULL);
-      if (base_copy == NULL)
+      err = setlocale_null (LC_CTYPE, base_name, sizeof (base_name));
+      if (err)
         {
-          int saved_errno = errno;
-          free (base_name);
-          errno = saved_errno;
+          errno = err;
           return NULL;
         }
+      base_copy = newlocale (LC_ALL_MASK, base_name, NULL);
+      if (base_copy == NULL)
+        return NULL;
 
       for (i = 0; i < SIZEOF (categories); i++)
         {
           int category = categories[i].cat;
           int category_mask = categories[i].mask;
-          const char *name = setlocale (category, NULL);
+          char name[SETLOCALE_NULL_MAX];
+
+          err = setlocale_null (category, name, sizeof (name));
+          if (err)
+            {
+              errno = err;
+              return NULL;
+            }
           if (strcmp (name, base_name) != 0)
             {
               locale_t copy = newlocale (category_mask, name, base_copy);
@@ -96,7 +101,6 @@ rpl_duplocale (locale_t locale)
                 {
                   int saved_errno = errno;
                   freelocale (base_copy);
-                  free (base_name);
                   errno = saved_errno;
                   return NULL;
                 }
@@ -106,7 +110,6 @@ rpl_duplocale (locale_t locale)
             }
         }
 
-      free (base_name);
       return base_copy;
     }
 
diff --git a/m4/duplocale.m4 b/m4/duplocale.m4
index fb5e602..3900b53 100644
--- a/m4/duplocale.m4
+++ b/m4/duplocale.m4
@@ -1,4 +1,4 @@
-# duplocale.m4 serial 11
+# duplocale.m4 serial 12
 dnl Copyright (C) 2009-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,6 +8,7 @@ AC_DEFUN([gl_FUNC_DUPLOCALE],
 [
   AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
   AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([gl_FUNC_SETLOCALE_NULL])
   AC_CHECK_FUNCS_ONCE([duplocale])
   if test $ac_cv_func_duplocale = yes; then
     dnl Check against glibc bug where duplocale crashes.
@@ -109,6 +110,12 @@ int main ()
   else
     HAVE_DUPLOCALE=0
   fi
+  if test $REPLACE_DUPLOCALE = 1; then
+    LIB_DUPLOCALE="$LIB_SETLOCALE_NULL"
+  else
+    LIB_DUPLOCALE=
+  fi
+  AC_SUBST([LIB_DUPLOCALE])
 ])
 
 # Prerequisites of lib/duplocale.c.
diff --git a/modules/duplocale b/modules/duplocale
index 08eca3c..aaa12cd 100644
--- a/modules/duplocale
+++ b/modules/duplocale
@@ -7,6 +7,7 @@ m4/duplocale.m4
 
 Depends-on:
 locale
+setlocale-null  [test $REPLACE_DUPLOCALE = 1]
 
 configure.ac:
 gl_FUNC_DUPLOCALE
@@ -21,6 +22,9 @@ Makefile.am:
 Include:
 <locale.h>
 
+Link:
+$(LIB_DUPLOCALE)
+
 License:
 LGPL
 
diff --git a/modules/duplocale-tests b/modules/duplocale-tests
index 29b2a1a..6545c4e 100644
--- a/modules/duplocale-tests
+++ b/modules/duplocale-tests
@@ -15,3 +15,4 @@ gt_FUNC_USELOCALE
 Makefile.am:
 TESTS += test-duplocale
 check_PROGRAMS += test-duplocale
+test_duplocale_LDADD = $(LDADD) @LIB_DUPLOCALE@




reply via email to

[Prev in Thread] Current Thread [Next in Thread]