From 5f6d86b50bebf5458ab1becf4de2c5e5f066122b Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sat, 11 Apr 2026 14:42:57 +0100 Subject: [PATCH] gkeyfile: Fix a one-byte heap under-read with g_key_file_get_locale_string_list() If this method was called on a key file key which has an empty value, `len == 0` and this leads to a one-byte under-read off the start of the key file buffer. Spotted by linhlhq as #YWH-PGM9867-200. The suggested fix is theirs, and the unit test is adapted from their report. I added the fuzzing test. Signed-off-by: Philip Withnall Fixes: #3930 --- fuzzing/fuzz_key.c | 9 +++++++++ glib/gkeyfile.c | 2 +- glib/tests/keyfile.c | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/fuzzing/fuzz_key.c b/fuzzing/fuzz_key.c index 77cb684aef..7d00443310 100644 --- a/fuzzing/fuzz_key.c +++ b/fuzzing/fuzz_key.c @@ -26,11 +26,20 @@ test_parse (const gchar *data, GKeyFileFlags flags) { GKeyFile *key = NULL; + char *comment = NULL; + char **list = NULL; key = g_key_file_new (); g_key_file_load_from_data (key, (const gchar*) data, size, G_KEY_FILE_NONE, NULL); + /* Also try some additional parsing and see if it crashes */ + comment = g_key_file_get_comment (key, "group", "key", NULL); + g_free (comment); + + list = g_key_file_get_locale_string_list (key, "group", "key", "de", NULL, NULL); + g_strfreev (list); + g_key_file_free (key); } diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index 84ddddc387..5ee2296f21 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -2462,7 +2462,7 @@ g_key_file_get_locale_string_list (GKeyFile *key_file, } len = strlen (value); - if (value[len - 1] == key_file->list_separator) + if (len > 0 && value[len - 1] == key_file->list_separator) value[len - 1] = '\0'; list_separator[0] = key_file->list_separator; diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c index 64a9ec317b..da5cad8e0e 100644 --- a/glib/tests/keyfile.c +++ b/glib/tests/keyfile.c @@ -889,6 +889,28 @@ test_locale_string_multiple_loads (void) g_free (old_locale); } +static void +test_locale_string_empty (void) +{ + GKeyFile *keyfile = NULL; + GError *local_error = NULL; + const char *data = + "[valid]\n" + "key1=\n"; + + g_test_summary ("Check that loading an empty translatable string works"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3930"); + + keyfile = g_key_file_new (); + + g_key_file_load_from_data (keyfile, data, -1, G_KEY_FILE_NONE, &local_error); + g_assert_no_error (local_error); + + check_locale_string_list_value (keyfile, "valid", "key1", NULL, NULL); + + g_key_file_free (keyfile); +} + static void test_lists (void) { @@ -2011,6 +2033,7 @@ main (int argc, char *argv[]) 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/locale-string/empty", test_locale_string_empty); 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); -- GitLab