bug-gettext
[Top][All Lists]
Advanced

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

[bug-gettext] [PATCH] Make libintl_setlocale fail more gracefully


From: Dapeng Gao
Subject: [bug-gettext] [PATCH] Make libintl_setlocale fail more gracefully
Date: Sat, 11 Aug 2018 00:28:10 +0800
User-agent: NeoMutt/20180716-171-eb8b46

Hi,

I patched `libintl_setlocale` to fail more gracefully when it. 
Specifically, whenver the original implementation would fail and return 
NULL, the patched version makes a last effort to call `setlocale` using 
the user's supplied parameters. The only exception where the function 
will not make this last effort is when it fails under some specific 
conditions when running in Windows.

I am not sure if this new behaviour will cause any surprises, but it 
does fix the bug in my use case.

This is my first contribution, so I am not very familiar with the 
development process here. I sincerely welcome any feedback or guidance. 
Thank you!

Best wishes,
Dapeng

---
  gettext-runtime/intl/setlocale.c | 122 +++++++++++++++++++--------------------
  1 file changed, 59 insertions(+), 63 deletions(-)

diff --git a/gettext-runtime/intl/setlocale.c b/gettext-runtime/intl/setlocale.c
index df1991825..516c179e1 100644
--- a/gettext-runtime/intl/setlocale.c
+++ b/gettext-runtime/intl/setlocale.c
@@ -818,10 +818,16 @@ DLL_EXPORTED
  char *
  libintl_setlocale (int category, const char *locale)
  {
-  if (locale != NULL && locale[0] == '\0')
+  char *result = NULL;
+
+  if (locale == NULL)
+    goto fail;
+
+  if (category == LC_ALL)
      {
-      /* A request to the set the current locale to the default locale.  */
-      if (category == LC_ALL)
+      char *saved_locale;
+
+      if (locale[0] == '\0')
          {
            /* Set LC_CTYPE first.  Then the other categories.  */
            static int const categories[] =
@@ -832,43 +838,41 @@ libintl_setlocale (int category, const char *locale)
                LC_MONETARY,
                LC_MESSAGES
              };
-          char *saved_locale;
-          const char *base_name;
-          unsigned int i;
  
            /* Back up the old locale, in case one of the steps fails.  */
            saved_locale = setlocale (LC_ALL, NULL);
            if (saved_locale == NULL)
-            return NULL;
+            goto fail;
            saved_locale = strdup (saved_locale);
            if (saved_locale == NULL)
-            return NULL;
+            goto fail;
  
            /* Set LC_CTYPE category.  Set all other categories (except possibly
               LC_MESSAGES) to the same value in the same call; this is likely 
to
               save calls.  */
-          base_name =
+          const char *base_name =
              gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
            if (base_name == NULL)
              base_name = gl_locale_name_default ();
  
            if (setlocale_unixlike (LC_ALL, base_name) == NULL)
-            goto fail;
+            goto cleanup;
+
  # if defined _WIN32 && ! defined __CYGWIN__
            /* On native Windows, setlocale(LC_ALL,...) may succeed but set the
               LC_CTYPE category to an invalid value ("C") when it does not
               support the specified encoding.  Report a failure instead.  */
            if (strchr (base_name, '.') != NULL
                && strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
-            goto fail;
+            goto win32_restore;
  # endif
  
-          for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
+          for (size_t i = 0; i < sizeof (categories) / sizeof (categories[0]); 
i++)
              {
                int cat = categories[i];
-              const char *name;
  
-              name = gl_locale_name_environ (cat, category_to_name (cat));
+              const char *name =
+                gl_locale_name_environ (cat, category_to_name (cat));
                if (name == NULL)
                  name = gl_locale_name_default ();
  
@@ -880,80 +884,72 @@ libintl_setlocale (int category, const char *locale)
  # endif
                   )
                  if (setlocale_single (cat, name) == NULL)
-                  goto fail;
+                  goto restore;
              }
  
            /* All steps were successful.  */
-          ++_nl_msg_cat_cntr;
-          free (saved_locale);
-          return setlocale (LC_ALL, NULL);
-
-        fail:
-          if (saved_locale[0] != '\0') /* don't risk an endless recursion */
-            setlocale (LC_ALL, saved_locale);
-          free (saved_locale);
-          return NULL;
+          result = setlocale (LC_ALL, NULL);
+          goto cleanup;
          }
-      else
-        {
-          char *result;
-          const char *name =
-            gl_locale_name_environ (category, category_to_name (category));
-          if (name == NULL)
-            name = gl_locale_name_default ();
-
-          result = setlocale_single (category, name);
-          if (result != NULL)
-            ++_nl_msg_cat_cntr;
-          return result;
-        }
-    }
-  else
-    {
  # if defined _WIN32 && ! defined __CYGWIN__
-      if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL)
+      else if (strchr (locale, '.') != NULL)
          {
-          char *saved_locale;
-
            /* Back up the old locale.  */
            saved_locale = setlocale (LC_ALL, NULL);
            if (saved_locale == NULL)
-            return NULL;
+            goto fail;
            saved_locale = strdup (saved_locale);
            if (saved_locale == NULL)
-            return NULL;
+            goto fail;
  
            if (setlocale_unixlike (LC_ALL, locale) == NULL)
-            {
-              free (saved_locale);
-              return NULL;
-            }
+            goto win32_cleanup;
  
            /* On native Windows, setlocale(LC_ALL,...) may succeed but set the
               LC_CTYPE category to an invalid value ("C") when it does not
               support the specified encoding.  Report a failure instead.  */
            if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
-            {
-              if (saved_locale[0] != '\0') /* don't risk an endless recursion 
*/
-                setlocale (LC_ALL, saved_locale);
-              free (saved_locale);
-              return NULL;
-            }
+            goto win32_restore;
  
            /* It was really successful.  */
-          ++_nl_msg_cat_cntr;
-          free (saved_locale);
-          return setlocale (LC_ALL, NULL);
+          result = setlocale (LC_ALL, NULL);
+          goto cleanup;
          }
-      else
  # endif
+      else
          {
-          char *result = setlocale_single (category, locale);
-          if (result != NULL)
-            ++_nl_msg_cat_cntr;
-          return result;
+          goto fail;
          }
+# if defined _WIN32 && ! defined __CYGWIN__
+    win32_restore:
+      if (saved_locale[0] != '\0') /* don't risk an endless recursion */
+        setlocale (LC_ALL, saved_locale);
+    win32_cleanup:
+      free (saved_locale);
+      return NULL;
+# endif
+    restore:
+      if (saved_locale[0] != '\0') /* don't risk an endless recursion */
+        setlocale (LC_ALL, saved_locale);
+    cleanup:
+      free (saved_locale);
      }
+  else if (locale[0] == '\0')
+    {
+      const char *name =
+        gl_locale_name_environ (category, category_to_name (category));
+      if (name == NULL)
+        name = gl_locale_name_default ();
+
+      result = setlocale_single (category, name);
+    }
+
+fail:
+  if (result == NULL)
+    result = setlocale_single (category, locale);
+  if (result != NULL)
+    ++_nl_msg_cat_cntr;
+  return result;
  }
  
  # if HAVE_NEWLOCALE
-- 
2.15.1 (Apple Git-101)




reply via email to

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