diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2009-11-26 09:38:31 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2009-12-03 09:37:20 +1000 |
commit | 83fdb27df4ddc2fb088ddf2ec65f0db6b7c57287 (patch) | |
tree | 2d4ab16c1b77dddd183a52529addd532773ccb6c | |
parent | 9632775f2195e3448fcc402a3743f3368a8a1c9c (diff) |
Don't smash the event_vec if num_events differs between lib and server.
If the library extension thinks there's more events to an extension than the
server actually has, the event_vec for the overlapping range can get
overwritten. This depends on the initialization order of the libraries.
Reported-by: Nathan Kidd
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Julien Cristau <jcristau@debian.org>
-rw-r--r-- | src/extutil.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/src/extutil.c b/src/extutil.c index 8f4923a..a8f4d5d 100644 --- a/src/extutil.c +++ b/src/extutil.c @@ -103,6 +103,7 @@ XExtDisplayInfo *XextAddDisplay ( int nevents, XPointer data) { + static unsigned char ext_handlers[64] = {0}; XExtDisplayInfo *dpyinfo; dpyinfo = (XExtDisplayInfo *) Xmalloc (sizeof (XExtDisplayInfo)); @@ -117,10 +118,54 @@ XExtDisplayInfo *XextAddDisplay ( */ if (dpyinfo->codes) { int i, j; + int idx = dpyinfo->codes->first_event & 0x3f; + + + /* Xlib extensions use compiled in event numbers. A new library + * against an older server may thus expect a different (higher) + * number of events than the server will send. We have no way of + * knowing the number of events for an extension, the server won't + * tell us. + * + * Depending on the extension initialization order, this smashes the + * event_vec[type] for anything after the extension with the + * different number of events. + * + * e.g. server with inputproto 1.3 expects 15 events, libXi with + * inputproto 2.0 expects 17 events. + * base code is 80, events [80,96] are handled by libXi. events [95, + * 96] belong to the next extension already though. + * This requires XI to be initialized after the extension occupying + * the next range of event codes. + * + * To avoid this, we have a zeroed out array of extension handlers. + * If an extension handler for an event type is already set, and the + * previous event code (before base_code) is the same extension, we + * have the nevents conflict. Unset all those handlers and allow + * overwriting them with the new handlers. + * + * If a handler for a (base + n) event is already set, stop + * registering this extension for the event codes. + * + * event_codes are subtracted by 64 since we don't need to worry + * about core. + */ + + if (idx && ext_handlers[idx - 1] == ext_handlers[idx]) { + for (i = idx; i < 64; i++) { + if (ext_handlers[idx - 1] == ext_handlers[i]) + ext_handlers[i] = 0; + else + break; + } + } - for (i = 0, j = dpyinfo->codes->first_event; i < nevents; i++, j++) { + for (i = 0, j = dpyinfo->codes->first_event; i < nevents; i++, j++, idx++) { + if (ext_handlers[idx]) /* don't smash the following extension */ + break; XESetWireToEvent (dpy, j, hooks->wire_to_event); XESetEventToWire (dpy, j, hooks->event_to_wire); + ext_handlers[idx] = dpyinfo->codes->first_event & 0x3f; } /* register extension for XGE */ |