[gnome-initial-setup/mcatanzaro/uselocale] Fix unsafe usage of setlocale()



commit e20c2d303184a402f5db4fde3515eddac22bd3bf
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Wed Feb 20 22:59:56 2019 -0600

    Fix unsafe usage of setlocale()
    
    setlocale() is MT-Unsafe so let's replace its usage with uselocale().
    Much safer! The locale is changed only for the main thread. Secondary
    threads will still get the global locale, but so what.
    
    Fixes #53

 gnome-initial-setup/gis-driver.c                   | 62 +++++++++++++++-------
 gnome-initial-setup/gis-driver.h                   |  4 +-
 .../pages/language/gis-language-page.c             |  4 +-
 .../pages/language/gis-welcome-widget.c            | 13 +++--
 gnome-initial-setup/pages/region/gis-region-page.c |  3 +-
 5 files changed, 56 insertions(+), 30 deletions(-)
---
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index 989f47a..aa529cc 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -78,6 +78,8 @@ struct _GisDriverPrivate {
   GisDriverMode mode;
   UmAccountMode account_mode;
   gboolean small_screen;
+
+  locale_t locale;
 };
 typedef struct _GisDriverPrivate GisDriverPrivate;
 
@@ -95,6 +97,12 @@ gis_driver_finalize (GObject *object)
 
   g_clear_object (&priv->user_account);
 
+  if (priv->locale != (locale_t) 0)
+    {
+      uselocale (LC_GLOBAL_LOCALE);
+      freelocale (priv->locale);
+    }
+
   G_OBJECT_CLASS (gis_driver_parent_class)->finalize (object);
 }
 
@@ -155,6 +163,41 @@ gis_driver_get_user_language (GisDriver *driver)
   return priv->lang_id;
 }
 
+static void
+gis_driver_real_locale_changed (GisDriver *driver)
+{
+  GisDriverPrivate *priv = gis_driver_get_instance_private (driver);
+  GtkTextDirection direction;
+
+  direction = gtk_get_locale_direction ();
+  gtk_widget_set_default_direction (direction);
+
+  rebuild_pages (driver);
+  gis_assistant_locale_changed (priv->assistant);
+}
+
+static void
+gis_driver_locale_changed (GisDriver *driver)
+{
+  g_signal_emit (G_OBJECT (driver), signals[LOCALE_CHANGED], 0);
+}
+
+void
+gis_driver_set_locale (GisDriver *driver, const gchar *lang_id)
+{
+  GisDriverPrivate *priv = gis_driver_get_instance_private (driver);
+  locale_t locale;
+
+  locale = newlocale (LC_MESSAGES_MASK, lang_id, (locale_t) 0);
+  uselocale (locale);
+
+  if (priv->locale != (locale_t) 0 && priv->locale != LC_GLOBAL_LOCALE)
+    freelocale (priv->locale);
+  priv->locale = locale;
+
+  gis_driver_locale_changed (driver);
+}
+
 void
 gis_driver_set_username (GisDriver *driver, const gchar *username)
 {
@@ -221,25 +264,6 @@ gis_driver_hide_window (GisDriver *driver)
   gtk_widget_hide (GTK_WIDGET (priv->main_window));
 }
 
-static void
-gis_driver_real_locale_changed (GisDriver *driver)
-{
-  GisDriverPrivate *priv = gis_driver_get_instance_private (driver);
-  GtkTextDirection direction;
-
-  direction = gtk_get_locale_direction ();
-  gtk_widget_set_default_direction (direction);
-
-  rebuild_pages (driver);
-  gis_assistant_locale_changed (priv->assistant);
-}
-
-void
-gis_driver_locale_changed (GisDriver *driver)
-{
-  g_signal_emit (G_OBJECT (driver), signals[LOCALE_CHANGED], 0);
-}
-
 GisDriverMode
 gis_driver_get_mode (GisDriver *driver)
 {
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
index 9eb408e..ce2db12 100644
--- a/gnome-initial-setup/gis-driver.h
+++ b/gnome-initial-setup/gis-driver.h
@@ -65,7 +65,6 @@ typedef enum {
 GType gis_driver_get_type (void);
 
 GisAssistant *gis_driver_get_assistant (GisDriver *driver);
-void gis_driver_locale_changed (GisDriver *driver);
 
 void gis_driver_set_user_permissions (GisDriver   *driver,
                                       ActUser     *user,
@@ -85,6 +84,9 @@ void gis_driver_set_user_language (GisDriver   *driver,
 
 const gchar *gis_driver_get_user_language (GisDriver   *driver);
 
+void gis_driver_set_locale (GisDriver   *driver,
+                            const gchar *lang_id);
+
 void gis_driver_set_username (GisDriver   *driver,
                               const gchar *username);
 const gchar *gis_driver_get_username (GisDriver *driver);
diff --git a/gnome-initial-setup/pages/language/gis-language-page.c 
b/gnome-initial-setup/pages/language/gis-language-page.c
index a4afe44..0eed8a9 100644
--- a/gnome-initial-setup/pages/language/gis-language-page.c
+++ b/gnome-initial-setup/pages/language/gis-language-page.c
@@ -123,7 +123,7 @@ language_changed (CcLanguageChooser  *chooser,
   priv->new_locale_id = cc_language_chooser_get_language (chooser);
   driver = GIS_PAGE (page)->driver;
 
-  setlocale (LC_MESSAGES, priv->new_locale_id);
+  gis_driver_set_locale (driver, priv->new_locale_id);
   gtk_widget_set_default_direction (gtk_get_locale_direction ());
 
   if (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER) {
@@ -157,8 +157,6 @@ language_changed (CcLanguageChooser  *chooser,
 
   gis_welcome_widget_show_locale (GIS_WELCOME_WIDGET (priv->welcome_widget),
                                   priv->new_locale_id);
-
-  gis_driver_locale_changed (driver);
 }
 
 static void
diff --git a/gnome-initial-setup/pages/language/gis-welcome-widget.c 
b/gnome-initial-setup/pages/language/gis-welcome-widget.c
index 87b28d4..37b000f 100644
--- a/gnome-initial-setup/pages/language/gis-welcome-widget.c
+++ b/gnome-initial-setup/pages/language/gis-welcome-widget.c
@@ -111,18 +111,21 @@ gis_welcome_widget_unmap (GtkWidget *widget)
 static char *
 welcome (const char *locale_id)
 {
-  char *current_locale_id;
+  locale_t locale;
+  locale_t old_locale;
   char *welcome;
 
-  current_locale_id = g_strdup (setlocale (LC_MESSAGES, NULL));
-  setlocale (LC_MESSAGES, locale_id);
+  locale = newlocale (LC_MESSAGES_MASK, locale_id, (locale_t) 0);
+  old_locale = uselocale (locale);
+
   /* Translators: This is meant to be a warm, engaging welcome message,
    * like greeting somebody at the door. If the exclamation mark is not
    * suitable for this in your language you may replace it.
    */
   welcome = _("Welcome!");
-  setlocale (LC_MESSAGES, current_locale_id);
-  g_free (current_locale_id);
+
+  uselocale (old_locale);
+  freelocale (locale);
 
   return welcome;
 }
diff --git a/gnome-initial-setup/pages/region/gis-region-page.c 
b/gnome-initial-setup/pages/region/gis-region-page.c
index 5a31b9c..898a352 100644
--- a/gnome-initial-setup/pages/region/gis-region-page.c
+++ b/gnome-initial-setup/pages/region/gis-region-page.c
@@ -120,8 +120,7 @@ region_changed (CcRegionChooser  *chooser,
   priv->new_locale_id = cc_region_chooser_get_locale (chooser);
   driver = GIS_PAGE (page)->driver;
 
-  setlocale (LC_MESSAGES, priv->new_locale_id);
-  gis_driver_locale_changed (driver);
+  gis_driver_set_locale (driver, priv->new_locale_id);
 
   if (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER) {
       if (g_permission_get_allowed (priv->permission)) {


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