[PATCH xserver 1/2] Xi: fix byte-swapping of button labels

Roman Kapl code at rkapl.cz
Thu Jun 7 01:31:41 UTC 2018


The byte-swapping code forgot that the xXIButtonInfo is followed by a
button mask, not directly by the button labels. This resulted in client
crashes in cross-endian setups, for example in `xinput list --long`,
since the client got an invalid atom.

A new function was introduced to get the right positions for the label
and mask data.

Signed-off-by: Roman Kapl <code at rkapl.cz>
---
 Xi/xiquerydevice.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index c0000f909..5f5a5f82f 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -237,6 +237,18 @@ SizeDeviceClasses(DeviceIntPtr dev)
     return len;
 }
 
+/**
+ * Get pointers to button information areas holding button mask and labels.
+ */
+static void
+ButtonInfoData(xXIButtonInfo *info, int *mask_words, unsigned char **mask,
+               Atom **atoms)
+{
+    *mask_words = bytes_to_int32(bits_to_bytes(info->num_buttons));
+    *mask = (unsigned char*) &info[1];
+    *atoms = (Atom*) ((*mask) + (*mask_words) * 4);
+}
+
 /**
  * Write button information into info.
  * @return Number of bytes written into info.
@@ -245,21 +257,20 @@ int
 ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
 {
     unsigned char *bits;
+    Atom *labels;
     int mask_len;
     int i;
 
     if (!dev || !dev->button)
         return 0;
 
-    mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
-
     info->type = ButtonClass;
     info->num_buttons = dev->button->numButtons;
+    ButtonInfoData(info, &mask_len, &bits, &labels);
     info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
         info->num_buttons + mask_len;
     info->sourceid = dev->button->sourceid;
 
-    bits = (unsigned char *) &info[1];
     memset(bits, 0, mask_len * 4);
 
     if (reportState)
@@ -267,8 +278,7 @@ ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
             if (BitIsOn(dev->button->down, i))
                 SetBit(bits, i);
 
-    bits += mask_len * 4;
-    memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
+    memcpy(labels, dev->button->labels, dev->button->numButtons * sizeof(Atom));
 
     return info->length * 4;
 }
@@ -277,13 +287,17 @@ static void
 SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info)
 {
     Atom *btn;
+    int mask_len;
+    unsigned char *mask;
+
     int i;
+    ButtonInfoData(info, &mask_len, &mask, &btn);
 
     swaps(&info->type);
     swaps(&info->length);
     swaps(&info->sourceid);
 
-    for (i = 0, btn = (Atom *) &info[1]; i < info->num_buttons; i++, btn++)
+    for (i = 0 ; i < info->num_buttons; i++, btn++)
         swapl(btn);
 
     swaps(&info->num_buttons);
-- 
2.17.1



More information about the xorg-devel mailing list