gkeyfile: Fix crash when parsing translations on a second load

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 <pwithnall@endlessos.org>

Fixes: #2361
This commit is contained in:
Philip Withnall 2021-03-23 16:28:31 +00:00
parent 164da19983
commit 34e4841854
2 changed files with 44 additions and 0 deletions

View File

@ -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)
{

View File

@ -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);