dix: Correctly save replayed event into GrabInfoRec
When processing events we operate on InternalEvent pointers. They may actually refer to a an instance of DeviceEvent, GestureEvent or any other event that comprises the InternalEvent union. This works well in practice because we always look into event type before doing anything, except in the case of copying the event. *dst_event = *src_event would copy whole InternalEvent event and would cause out of bounds read in case the pointed to event was not InternalEvent but e.g. DeviceEvent. This regression has been introduced in23a8b62d34
. Fixes https://gitlab.freedesktop.org/xorg/xserver/-/issues/1261 Signed-off-by: Povilas Kanapickas <povilas@radix.lt> (cherry picked from commit6ef5c05728
)
This commit is contained in:
parent
cd3d21d8c4
commit
b713e717c3
|
@ -1524,7 +1524,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
|||
g = AllocGrab(devgrab);
|
||||
BUG_WARN(!g);
|
||||
|
||||
*dev->deviceGrab.sync.event = *ev;
|
||||
CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev);
|
||||
|
||||
/* The listener array has a sequence of grabs and then one event
|
||||
* selection. Implicit grab activation occurs through delivering an
|
||||
|
|
18
dix/events.c
18
dix/events.c
|
@ -467,6 +467,20 @@ WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
|
|||
return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* When processing events we operate on InternalEvent pointers. They may actually refer to a
|
||||
* an instance of DeviceEvent, GestureEvent or any other event that comprises the InternalEvent
|
||||
* union. This works well in practice because we always look into event type before doing anything,
|
||||
* except in the case of copying the event. Any copying of InternalEvent should use this function
|
||||
* instead of doing *dst_event = *src_event whenever it's not clear whether source event actually
|
||||
* points to full InternalEvent instance.
|
||||
*/
|
||||
void
|
||||
CopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event)
|
||||
{
|
||||
memcpy(dst_event, src_event, src_event->any.length);
|
||||
}
|
||||
|
||||
Mask
|
||||
GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
|
||||
{
|
||||
|
@ -3873,7 +3887,7 @@ void ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab,
|
|||
|
||||
if (grabinfo->sync.state == FROZEN_NO_EVENT)
|
||||
grabinfo->sync.state = FROZEN_WITH_EVENT;
|
||||
*grabinfo->sync.event = *real_event;
|
||||
CopyPartialInternalEvent(grabinfo->sync.event, real_event);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
|
@ -4455,7 +4469,7 @@ FreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event)
|
|||
case FREEZE_NEXT_EVENT:
|
||||
grabinfo->sync.state = FROZEN_WITH_EVENT;
|
||||
FreezeThaw(thisDev, TRUE);
|
||||
*grabinfo->sync.event = *event;
|
||||
CopyPartialInternalEvent(grabinfo->sync.event, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -676,6 +676,7 @@ extern void GestureEmitGestureEndToOwner(DeviceIntPtr dev, GestureInfoPtr gi);
|
|||
extern void ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev);
|
||||
|
||||
/* misc event helpers */
|
||||
extern void CopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event);
|
||||
extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients);
|
||||
extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event);
|
||||
extern Bool WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev);
|
||||
|
|
Loading…
Reference in New Issue