Commit f00e779ab5064ee2bd4bc2ffec75996a8f64e98d

Ran Benita 2014-08-08T17:21:28

x11/keymap: be more defensive about the number of modifiers There can be at most 16 vmods, and we rely on the facts that #vmods + NUM_REAL_MODS (8) <= XKB_MAX_MODS (32) when accessing keymap->mods.mods. But msb_pos() can potentially return up to #vmods = 32 if the server is malicious, so we need to truncate it. Signed-off-by: Ran Benita <ran234@gmail.com>

diff --git a/src/x11/keymap.c b/src/x11/keymap.c
index f852078..e3f989d 100644
--- a/src/x11/keymap.c
+++ b/src/x11/keymap.c
@@ -508,7 +508,8 @@ get_vmods(struct xkb_keymap *keymap, xcb_connection_t *conn,
 {
     uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map);
 
-    keymap->mods.num_mods = NUM_REAL_MODS + msb_pos(reply->virtualMods);
+    keymap->mods.num_mods =
+        NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
 
     for (unsigned i = 0; i < NUM_VMODS; i++) {
         if (reply->virtualMods & (1u << i)) {
@@ -918,7 +919,8 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
      * tells us which vmods exist (a vmod must have a name), so we fix
      * up the size here.
      */
-    keymap->mods.num_mods = NUM_REAL_MODS + msb_pos(reply->virtualMods);
+    keymap->mods.num_mods =
+        NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
 
     for (unsigned i = 0; i < NUM_VMODS; i++) {
         if (reply->virtualMods & (1u << i)) {