diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2009-08-03 16:46:11 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2009-08-13 10:58:39 +1000 |
commit | 55e1ea08d03d89ecc0f2db7652a4d15567204696 (patch) | |
tree | 81593bc7945aa2ce4fbc836a889dc772b0d5e7c3 /Xi | |
parent | 8ce4fde76fdf747fd3e00836c9c9c542e516ae9a (diff) |
Xi: get device changed data from DeviceChangedEvents, not the device (#23100)
If a new device posts an event while the DCE is in the queue, getting the
data from the device may result in invalid memory access.
X.Org Bug 23100 <http://bugs.freedesktop.org/show_bug.cgi?id=23100>
Diffstat (limited to 'Xi')
-rw-r--r-- | Xi/exevents.c | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index 85d14b09b..49eacb4d1 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -674,6 +674,69 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dc } +static int +AppendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo* info) +{ + uint32_t *kc; + int i; + + info->type = KeyClass; + info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1; + info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes; + info->sourceid = dce->deviceid; + + kc = (uint32_t*)&info[1]; + for (i = 0; i < info->num_keycodes; i++) + *kc++ = i + dce->keys.min_keycode; + + return info->length * 4; +} + +static int +AppendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo *info) +{ + unsigned char *bits; + int mask_len; + + mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons)); + + info->type = ButtonClass; + info->num_buttons = dce->buttons.num_buttons; + info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + + info->num_buttons + mask_len; + info->sourceid = dce->deviceid; + + bits = (unsigned char*)&info[1]; + memset(bits, 0, mask_len * 4); + /* FIXME: is_down? */ + + bits += mask_len * 4; + memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom)); + + return info->length * 4; +} + +static int +AppendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumber) +{ + info->type = ValuatorClass; + info->length = sizeof(xXIValuatorInfo)/4; + info->label = dce->valuators[axisnumber].name; + info->min.integral = dce->valuators[axisnumber].min; + info->min.frac = 0; + info->max.integral = dce->valuators[axisnumber].max; + info->max.frac = 0; + /* FIXME: value */ + info->value.integral = 0; + info->value.frac = 0; + info->resolution = dce->valuators[axisnumber].resolution; + info->number = axisnumber; + info->mode = dce->valuators[axisnumber].mode; /* Server doesn't have per-axis mode yet */ + info->sourceid = dce->deviceid; + + return info->length * 4; +} + /** * Send an XI2 DeviceChangedEvent to all interested clients. */ @@ -723,13 +786,13 @@ XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChanged if (dce->buttons.num_buttons) { dcce->num_classes++; - ptr += ListButtonInfo(device, (xXIButtonInfo*)ptr); + ptr += AppendButtonInfo(dce, (xXIButtonInfo*)ptr); } if (nkeys) { dcce->num_classes++; - ptr += ListKeyInfo(device, (xXIKeyInfo*)ptr); + ptr += AppendKeyInfo(dce, (xXIKeyInfo*)ptr); } if (dce->num_valuators) @@ -738,7 +801,7 @@ XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChanged dcce->num_classes += dce->num_valuators; for (i = 0; i < dce->num_valuators; i++) - ptr += ListValuatorInfo(device, (xXIValuatorInfo*)ptr, i); + ptr += AppendValuatorInfo(dce, (xXIValuatorInfo*)ptr, i); } /* we don't actually swap if there's a NullClient, swapping is done |