diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | lib/duplocale.c | 29 | ||||
-rw-r--r-- | m4/duplocale.m4 | 9 | ||||
-rw-r--r-- | modules/duplocale | 4 | ||||
-rw-r--r-- | modules/duplocale-tests | 1 |
5 files changed, 41 insertions, 14 deletions
@@ -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@ |