summaryrefslogtreecommitdiff
path: root/libgnome-desktop
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2021-04-22 11:29:18 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2021-04-22 11:49:22 +1000
commitaa7e344051170ea47585d3d72b1a36e3991121f9 (patch)
treebbd1a26056dd3a1efc96ba17021d8c9d61c99a72 /libgnome-desktop
parentbd3ec2204dfc66b1c602f7a1d0a687460ad9bce1 (diff)
downloadgnome-desktop-aa7e344051170ea47585d3d72b1a36e3991121f9.tar.gz
xkbinfo: only insert new layouts, skip over duplicate ones
This matches the behavior to the one in the old code path before libxkbregistry. This also fixes a use-after-free bug when a duplicate layout is present. The same layout struct is a member of multiple hashtables, specifically priv->layouts_table, priv->layouts_by_language and priv->layouts_by_country. When the duplicate layout is added, add_layouts calls g_hash_table_replace (priv->layouts_table, l->id, l) which frees the original layout - but the layouts_by_{country|language} still have that now-freed layout. Immediately afterwards, add_layouts calls add_layout_to_locale_tables () which calls add_layout_to_table () which triggers a use-after-free. Avoid all this by simply skipping any duplicate layout. Reproducible with gsettings set org.gnome.desktop.input-sources show-all-sources true valgrind /usr/libexec/gnome-desktop-debug/test-xkb-info Requires xkeyboard-config <= 2.32, it has a duplicate cm(mmuock) entry (one is marked exotic, hence the need for show-all-sources). Fixes #190 Bug analysis by Barnabás Pőcze (@pobrn) Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'libgnome-desktop')
-rw-r--r--libgnome-desktop/gnome-xkb-info.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/libgnome-desktop/gnome-xkb-info.c b/libgnome-desktop/gnome-xkb-info.c
index b2eca699..f2a3214b 100644
--- a/libgnome-desktop/gnome-xkb-info.c
+++ b/libgnome-desktop/gnome-xkb-info.c
@@ -268,6 +268,12 @@ add_layouts (GnomeXkbInfo *self,
l->iso3166Ids = g_slist_prepend (l->iso3166Ids, id);
}
+ if (g_hash_table_contains (priv->layouts_table, l->id))
+ {
+ g_clear_pointer (&l, free_layout);
+ return;
+ }
+
g_hash_table_replace (priv->layouts_table, l->id, l);
add_layout_to_locale_tables (l,
priv->layouts_by_language,