client/X11: Avoid crash in XGetDeviceButtonMapping()
XOpenDevice() may fail and return NULL, so try to find the first
pointer device that can be opened, and ensure that ptr_dev argument
is not NULL before passing it to XGetDeviceButtonMapping().
@@ -979,7 +979,6 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
{
#ifdef WITH_XI
int opcode, event, error;
- int xid;
XDevice* ptr_dev;
XExtensionVersion* version;
XDeviceInfo* devices1;
@@ -989,7 +988,7 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
if (XQueryExtension(xfc->display, "XInputExtension", &opcode, &event, &error))
{
WLog_DBG(TAG, "Searching for XInput pointer device");
- xid = INVALID_XID;
+ ptr_dev = NULL;
/* loop through every device, looking for a pointer */
version = XGetExtensionVersion(xfc->display, INAME);
@@ -1005,7 +1004,8 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
if ((devices2[i].use == XISlavePointer) &&
(strncmp(devices2[i].name, TEST_PTR_STR, TEST_PTR_LEN) != 0))
{
- xid = devices2[i].deviceid;
+ ptr_dev = XOpenDevice(xfc->display, devices2[i].deviceid);
+ if (ptr_dev)
break;
}
}
@@ -1025,7 +1025,8 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
if ((devices1[i].use == IsXExtensionPointer) &&
(strncmp(devices1[i].name, TEST_PTR_STR, TEST_PTR_LEN) != 0))
{
- xid = devices1[i].id;
+ ptr_dev = XOpenDevice(xfc->display, devices1[i].id);
+ if (ptr_dev)
break;
}
}
@@ -1038,10 +1039,9 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
/* get button mapping from input extension if there is a pointer device; */
/* otherwise leave unchanged. */
- if (xid != INVALID_XID)
+ if (ptr_dev)
{
- WLog_DBG(TAG, "Pointer device: %d", xid);
- ptr_dev = XOpenDevice(xfc->display, xid);
+ WLog_DBG(TAG, "Pointer device: %d", ptr_dev->device_id);
XGetDeviceButtonMapping(xfc->display, ptr_dev, x11_map, NUM_BUTTONS_MAPPED);
XCloseDevice(xfc->display, ptr_dev);
}
