Xlib contract for XEvent up/down-casting

Keith Packard keithp at keithp.com
Sun Dec 4 18:08:41 UTC 2022


Jeremy Huddleston Sequoia <jeremyhu at apple.com> writes:

> So the problem is clear, but I'm not sure which side needs to change.

Probably both?

How about a simple hack in XPutBackEvent that uses _XEventToWire
followed by _XWireToEvent? That would also clear out any unused bits
from the event before inserting it into the queue and check to make sure
the event type was valid.

diff --git a/src/PutBEvent.c b/src/PutBEvent.c
index 0f9df342..f7b74b31 100644
--- a/src/PutBEvent.c
+++ b/src/PutBEvent.c
@@ -79,9 +79,22 @@ XPutBackEvent (
     register XEvent *event)
        {
        int ret;
+       xEvent wire = {0};
+       XEvent lib = {0};
+       Status (*fp)(Display *, XEvent *, xEvent *);
+       int type = event->type & 0177;
 
        LockDisplay(dpy);
-       ret = _XPutBackEvent(dpy, event);
+       fp = dpy->wire_vec[type];
+       if (fp == NULL)
+               fp = _XEventToWire;
+       ret = (*fp)(dpy, event, &wire);
+       if (ret)
+       {
+               ret = (*dpy->event_vec[type])(dpy, &lib, &wire);
+               if (ret)
+                       ret = _XPutBackEvent(dpy, &lib);
+       }
        UnlockDisplay(dpy);
        return ret;
        }

> With a quick grep through our source code, I see some (XEvent *)
> casting in many other locations (xterm, cairo, libXt, ...).  So is the
> burden on the caller to ensure that their events are properly padded
> into an XEvent, or is the burden on the recipient of an XEvent to
> ensure that they determine the event type before reading the event?

Yeah, that's problematic behavior for sure; one should never cast to a
pointer of a type which is larger. But, we can't exactly fix the Xlib
API to make that unnecessary.

I guess the question is whether there are other places in Xlib which
take an XEvent * and access fields beyond those defined by the related
union member?

> Or is this unique to XPutBackEvent(), and freeglut is abusing
> XPutBackEvent() since XPutBackEvent() should be use to "push an event
> back onto the head of the display's event queue" (meaning the event
> should have previously been popped from the queue and thus be
> appropriately sized, not something created on the stack of arbitrary
> size?

The XPutBackEvent docs don't explicitly require that the event come from
the queue, it seems to use that only as an example.

-- 
-keith
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <https://lists.x.org/archives/xorg-devel/attachments/20221204/18d4a278/attachment.sig>


More information about the xorg-devel mailing list