summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-12-15 23:07:28 +0100
committerBruno Haible <bruno@clisp.org>2019-12-15 23:44:03 +0100
commit3a2a6ea2d90664ffef51e6f4be405ea63221dad2 (patch)
tree5ab9e0715907b131abb0061ce910e53800d546ea
parent4110c01cb60ea810e5f4abb38224eac0b1560462 (diff)
downloadgnulib-3a2a6ea2d90664ffef51e6f4be405ea63221dad2.tar.gz
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).
-rw-r--r--ChangeLog12
-rw-r--r--lib/duplocale.c29
-rw-r--r--m4/duplocale.m49
-rw-r--r--modules/duplocale4
-rw-r--r--modules/duplocale-tests1
5 files changed, 41 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index af1d5bf903..4f46f01a4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2019-12-15 Bruno Haible <bruno@clisp.org>
+ 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).
+
+2019-12-15 Bruno Haible <bruno@clisp.org>
+
setlocale-null: Add tests.
* tests/test-setlocale_null.c: New file.
* tests/test-setlocale_null-one.c: New file.
diff --git a/lib/duplocale.c b/lib/duplocale.c
index 3b958bab51..d22a447a91 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 fb5e602a09..3900b53b5e 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 08eca3c261..aaa12cd09d 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 29b2a1a02d..6545c4e33a 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@