Backport upstream commit 5f6d86b50bebf5458ab1becf4de2c5e5f066122b
to fix CVE-2026-58014, a one-byte heap under-read in
g_key_file_get_locale_string_list() when called on a key with
an empty value. The fix adds a `len > 0` guard before accessing
value[len-1]. The patch also includes a unit test and fuzzing
test enhancement.
CVE: CVE-2026-58014
Upstream patches:
- 5f6d86b50b.patch
Resolves: RHEL-190604
This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.
Assisted-by: Ymir
102 lines
3.3 KiB
Diff
102 lines
3.3 KiB
Diff
From 2303fbb163c76f3b07d0ff3ba3c1b806bb94b780 Mon Sep 17 00:00:00 2001
|
|
From: Philip Withnall <pwithnall@gnome.org>
|
|
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 <pwithnall@gnome.org>
|
|
|
|
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 9f1f9187e..285bad26f 100644
|
|
--- a/fuzzing/fuzz_key.c
|
|
+++ b/fuzzing/fuzz_key.c
|
|
@@ -6,11 +6,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 0b58edb3f..aae03afb0 100644
|
|
--- a/glib/gkeyfile.c
|
|
+++ b/glib/gkeyfile.c
|
|
@@ -2409,7 +2409,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 975ef8167..215c973a5 100644
|
|
--- a/glib/tests/keyfile.c
|
|
+++ b/glib/tests/keyfile.c
|
|
@@ -800,6 +800,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)
|
|
{
|
|
@@ -1834,6 +1856,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);
|