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.hutte...@who-t.net>
---
Changes to previous version:
- whitespaces fixed
- loop now removes all excessive extension handlers (as Julien suggested)

 src/extutil.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/src/extutil.c b/src/extutil.c
index ac861ea..800971b 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 */
-- 
1.6.5.2
_______________________________________________
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Reply via email to