From 164da19983daf92cc9c90b57f1def2fb03f4d4bd Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 23 Mar 2021 16:27:49 +0000 Subject: [PATCH 1/2] gkeyfile: Drop a redundant check It should not be possible for `->locales` to be set without `->checked_locales` being set, so drop the redundant check. This helps with branch code coverage. Signed-off-by: Philip Withnall --- glib/gkeyfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index 50859164b..06c4b7c47 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -1232,7 +1232,7 @@ g_key_file_locale_is_interesting (GKeyFile *key_file, if (key_file->flags & G_KEY_FILE_KEEP_TRANSLATIONS) return TRUE; - if (!key_file->checked_locales && !key_file->locales) + if (!key_file->checked_locales) { key_file->locales = g_strdupv ((gchar **)g_get_language_names ()); key_file->checked_locales = TRUE; From 34e48418546e2a76c991d9780418401437a1af7a Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 23 Mar 2021 16:28:31 +0000 Subject: [PATCH 2/2] gkeyfile: Fix crash when parsing translations on a second load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the same `GKeyFile` is reused to load multiple different key files, any loads after the first which encounter translated keys will crash, because clearing the data from the first load cleared the cached language names, but didn’t clear `checked_locales`, so they were never reloaded. Signed-off-by: Philip Withnall Fixes: #2361 --- glib/gkeyfile.c | 1 + glib/tests/keyfile.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index 06c4b7c47..0b58edb3f 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -648,6 +648,7 @@ g_key_file_clear (GKeyFile *key_file) g_strfreev (key_file->locales); key_file->locales = NULL; } + key_file->checked_locales = FALSE; if (key_file->parse_buffer) { diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c index 7530bc8c3..975ef8167 100644 --- a/glib/tests/keyfile.c +++ b/glib/tests/keyfile.c @@ -758,6 +758,48 @@ test_locale_string (void) g_free (old_locale); } +static void +test_locale_string_multiple_loads (void) +{ + GKeyFile *keyfile = NULL; + GError *local_error = NULL; + gchar *old_locale = NULL; + guint i; + const gchar *data = + "[valid]\n" + "key1=v1\n" + "key1[de]=v1-de\n" + "key1[de_DE]=v1-de_DE\n" + "key1[de_DE.UTF8]=v1-de_DE.UTF8\n" + "key1[fr]=v1-fr\n" + "key1[en] =v1-en\n" + "key1[sr@Latn]=v1-sr\n"; + + g_test_summary ("Check that loading with translations multiple times works"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2361"); + + old_locale = g_strdup (setlocale (LC_ALL, NULL)); + g_setenv ("LANGUAGE", "de", TRUE); + setlocale (LC_ALL, ""); + + keyfile = g_key_file_new (); + + for (i = 0; i < 3; i++) + { + g_key_file_load_from_data (keyfile, data, -1, G_KEY_FILE_NONE, &local_error); + g_assert_no_error (local_error); + + check_locale_string_value (keyfile, "valid", "key1", "it", "v1"); + check_locale_string_value (keyfile, "valid", "key1", "de", "v1-de"); + check_locale_string_value (keyfile, "valid", "key1", "de_DE", "v1-de"); + } + + g_key_file_free (keyfile); + + setlocale (LC_ALL, old_locale); + g_free (old_locale); +} + static void test_lists (void) { @@ -1791,6 +1833,7 @@ main (int argc, char *argv[]) g_test_add_func ("/keyfile/boolean", test_boolean); g_test_add_func ("/keyfile/number", test_number); g_test_add_func ("/keyfile/locale-string", test_locale_string); + g_test_add_func ("/keyfile/locale-string/multiple-loads", test_locale_string_multiple_loads); g_test_add_func ("/keyfile/lists", test_lists); g_test_add_func ("/keyfile/lists-set-get", test_lists_set_get); g_test_add_func ("/keyfile/group-remove", test_group_remove);