See <https://savannah.gnu.org/bugs/?38162>.

On Mac OS X, if per-thread locale is disabled, libintl's dcigettext
implementation searches for known-translations in a cache using an empty
locale name ("") as a key.

So, if dcigettext is called twice on a same string with different global
locale settings, the search hits and returns the translation for a
locale previously set with setlocale().

I'm attaching a patch to fix this.  Although there are some whitespace
changes, it merely adds a guard:

  if (uselocale (NULL) != LC_GLOBAL_LOCALE)

to the cache lookup.

Regards,
-- 
Daiki Ueno
>From 755a995c7830780f2781ff64a339185b2740f306 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <[email protected]>
Date: Wed, 6 Mar 2013 13:32:45 +0900
Subject: [PATCH] dcigettext: Handle the case when per-thread locale is
 disabled on Mac OS X

---
 gettext-runtime/intl/ChangeLog    |  7 +++++++
 gettext-runtime/intl/dcigettext.c | 40 ++++++++++++++++++++++-----------------
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/gettext-runtime/intl/ChangeLog b/gettext-runtime/intl/ChangeLog
index 9eb4109..34868a3 100644
--- a/gettext-runtime/intl/ChangeLog
+++ b/gettext-runtime/intl/ChangeLog
@@ -1,3 +1,10 @@
+2013-03-06  Daiki Ueno  <[email protected]>
+
+	* dcigettext.c (DCIGETTEXT): Don't search for known translation
+	with thread locale, if per-thread locale is disabled on Mac OS X.
+	Reported by Guido Flohr at
+	<https://savannah.gnu.org/bugs/?38162>.
+
 2013-03-05  Daiki Ueno  <[email protected]>
 
 	* verify.h: Update copyright year.
diff --git a/gettext-runtime/intl/dcigettext.c b/gettext-runtime/intl/dcigettext.c
index be2dceb..9a58525 100644
--- a/gettext-runtime/intl/dcigettext.c
+++ b/gettext-runtime/intl/dcigettext.c
@@ -564,29 +564,35 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
   search.encoding = encoding;
 # endif
 
-  /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
-     tsearch calls can be fatal.  */
-  gl_rwlock_rdlock (tree_lock);
+# if HAVE_USELOCALE
+  if (uselocale (NULL) != LC_GLOBAL_LOCALE)
+# endif
+    {
+      /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
+         tsearch calls can be fatal.  */
+      gl_rwlock_rdlock (tree_lock);
 
-  foundp = (struct known_translation_t **) tfind (&search, &root, transcmp);
+      foundp = (struct known_translation_t **) tfind (&search, &root, transcmp);
 
-  gl_rwlock_unlock (tree_lock);
+      gl_rwlock_unlock (tree_lock);
 
-  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
-    {
-      /* Now deal with plural.  */
-      if (plural)
-	retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
-				(*foundp)->translation_length);
-      else
-	retval = (char *) (*foundp)->translation;
+      if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+        {
+          /* Now deal with plural.  */
+          if (plural)
+            retval = plural_lookup ((*foundp)->domain, n,
+                                    (*foundp)->translation,
+                                    (*foundp)->translation_length);
+          else
+            retval = (char *) (*foundp)->translation;
 
-      gl_rwlock_unlock (_nl_state_lock);
+          gl_rwlock_unlock (_nl_state_lock);
 # ifdef _LIBC
-      __libc_rwlock_unlock (__libc_setlocale_lock);
+          __libc_rwlock_unlock (__libc_setlocale_lock);
 # endif
-      __set_errno (saved_errno);
-      return retval;
+          __set_errno (saved_errno);
+          return retval;
+        }
     }
 #endif
 
-- 
1.8.1.2

Reply via email to