debian/changelog          |   10 ++++++++
 man/XListInputDevices.txt |   12 ++++++++-
 src/XGMotion.c            |    3 +-
 src/XGetBMap.c            |    3 +-
 src/XGetDCtl.c            |    6 +++-
 src/XGetFCtl.c            |    7 ++++-
 src/XGetKMap.c            |   14 +++++++++--
 src/XGetMMap.c            |   11 +++++++--
 src/XIQueryDevice.c       |   43 ++++++++++++++++++++++++++++++++---
 src/XListDev.c            |   56 ++++++++++++++++++++++++++++------------------
 src/XOpenDev.c            |   13 ++++++++--
 src/XQueryDv.c            |    8 ++++--
 12 files changed, 144 insertions(+), 42 deletions(-)

New commits:
commit 4103bd3e9dd7a9cd86a3bc8d9527b2121e321171
Author: Emilio Pozuelo Monfort <po...@debian.org>
Date:   Tue Oct 25 20:27:18 2016 +0200

    Upload to wheezy-security

diff --git a/debian/changelog b/debian/changelog
index 0444e6d..e53c614 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+libxi (2:1.6.1-1+deb7u2) wheezy-security; urgency=medium
+
+  * Cherry-pick upstream commit 19a9cd6:
+    CVE-2016-7945, CVE-2016-7946: Properly validate server responses
+    to mitigated out of bounds accesses and endless loops.
+  * Also cherry-pick upstream commits b843fe1, 43904c9, 7ac03c6c, 4c5c8d6,
+    which fix some issues in the above fix.
+
+ -- Emilio Pozuelo Monfort <po...@debian.org>  Thu, 27 Oct 2016 00:35:40 +0200
+
 libxi (2:1.6.1-1+deb7u1) wheezy-security; urgency=high
 
   * integer overflows calculating memory needs for replies [CVE-2013-1984]

commit 2fc0ca0a29079eca9dd508cd74f79ae7aad2eb56
Author: Emilio Pozuelo Monfort <po...@debian.org>
Date:   Tue Oct 25 21:31:19 2016 +0200

    Check that allocating a buffer succeeded
    
    Since we are going to write into the buffer, we should make sure the
    allocation didn't fail.
    
    Reported-by: Julien Cristau <jcris...@debian.org>
    Signed-off-by: Emilio Pozuelo Monfort <po...@debian.org>
    Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>

diff --git a/src/XIQueryDevice.c b/src/XIQueryDevice.c
index 4b49e97..3fc412e 100644
--- a/src/XIQueryDevice.c
+++ b/src/XIQueryDevice.c
@@ -66,17 +66,18 @@ XIQueryDevice(Display *dpy, int deviceid, int 
*ndevices_return)
     {
        *ndevices_return = reply.num_devices;
        info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
+       buf = Xmalloc(reply.length * 4);
     }
     else
     {
        *ndevices_return = 0;
        info = NULL;
+       buf = NULL;
     }
 
-    if (!info)
+    if (!info || !buf)
         goto error;
 
-    buf = Xmalloc(reply.length * 4);
     _XRead(dpy, buf, reply.length * 4);
     ptr = buf;
     end = buf + reply.length * 4;
@@ -135,9 +136,9 @@ error_loop:
         Xfree(info[i].name);
         Xfree(info[i].classes);
     }
+error:
     Xfree(info);
     Xfree(buf);
-error:
     UnlockDisplay(dpy);
     SyncHandle();
     *ndevices_return = -1;

commit 1ea0cd9c60f001136f68afbf77795d41f7ba38d1
Author: Emilio Pozuelo Monfort <po...@debian.org>
Date:   Tue Oct 25 21:31:18 2016 +0200

    Plug a memory leak
    
    Introduced in commit 19a9cd6.
    
    Reported-by: Julien Cristau <jcris...@debian.org>
    Signed-off-by: Emilio Pozuelo Monfort <po...@debian.org>
    Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>

diff --git a/src/XIQueryDevice.c b/src/XIQueryDevice.c
index 9a89430..4b49e97 100644
--- a/src/XIQueryDevice.c
+++ b/src/XIQueryDevice.c
@@ -135,6 +135,8 @@ error_loop:
         Xfree(info[i].name);
         Xfree(info[i].classes);
     }
+    Xfree(info);
+    Xfree(buf);
 error:
     UnlockDisplay(dpy);
     SyncHandle();

commit a8176a8417c8c1cd5946a305dbfeb290799abafa
Author: Peter Hutterer <peter.hutte...@who-t.net>
Date:   Thu Oct 13 13:33:11 2016 +1000

    XListInputDevices: don't touch ndevices in case of error
    
    We used to always set *ndevices to the number of devices returned by the
    server. This magically worked because we pretty much never returned an error
    except on faulty server or library implementations. With 19a9cd60 we now 
have
    more chances of getting an error, so the polite thing is to just leave 
*ndevices
    alone when we error out.
    
    Document it as such in the man page, just in case someone accidentally reads
    it.
    
    Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
    CC: Niels Ole Salscheider <niels_...@salscheider-online.de>
    Reviewed-by: Emil Velikov <emil.l.veli...@gmail.com>

diff --git a/man/XListInputDevices.txt b/man/XListInputDevices.txt
index 276660d..450f377 100644
--- a/man/XListInputDevices.txt
+++ b/man/XListInputDevices.txt
@@ -220,5 +220,13 @@ DESCRIPTION
    Floating. If the device is a master device, attached specifies
    the device ID of the master device this device is paired with.
 
-   To free the XDeviceInfo array created by XListInputDevices, use
-   XFreeDeviceList.
+RETURN VALUE
+------------
+
+   XListInputDevices returns a pointer to an array of XDeviceInfo
+   structs and sets ndevices_return to the number of elements in
+   that array. To free the XDeviceInfo array created by
+   XListInputDevices, use XFreeDeviceList.
+
+   On error, XListInputDevices returns NULL and ndevices_return is
+   left unmodified.
diff --git a/src/XListDev.c b/src/XListDev.c
index 45c16fe..d610207 100644
--- a/src/XListDev.c
+++ b/src/XListDev.c
@@ -174,7 +174,7 @@ ParseClassInfo(xAnyClassPtr *any, XAnyClassPtr *Any, int 
num_classes)
 XDeviceInfo *
 XListInputDevices(
     register Display   *dpy,
-    int                        *ndevices)
+    int                        *ndevices_return)
 {
     size_t s, size;
     xListInputDevicesReq *req;
@@ -189,6 +189,7 @@ XListInputDevices(
     int i;
     unsigned long rlen;
     XExtDisplayInfo *info = XInput_find_display(dpy);
+    int ndevices;
 
     LockDisplay(dpy);
     if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1)
@@ -204,8 +205,8 @@ XListInputDevices(
        return (XDeviceInfo *) NULL;
     }
 
-    if ((*ndevices = rep.ndevices)) {  /* at least 1 input device */
-       size = *ndevices * sizeof(XDeviceInfo);
+    if ((ndevices = rep.ndevices)) {   /* at least 1 input device */
+       size = ndevices * sizeof(XDeviceInfo);
        if (rep.length < (INT_MAX >> 2)) {
            rlen = rep.length << 2;     /* multiply length by 4    */
            slist = list = Xmalloc(rlen);
@@ -218,17 +219,17 @@ XListInputDevices(
        }
        _XRead(dpy, (char *)list, rlen);
 
-       any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
+       any = (xAnyClassPtr) ((char *)list + (ndevices * sizeof(xDeviceInfo)));
        sav_any = any;
        end = (char *)list + rlen;
-       for (i = 0; i < *ndevices; i++, list++) {
+       for (i = 0; i < ndevices; i++, list++) {
             if(SizeClassInfo(&any, end - (char *)any, (int)list->num_classes, 
&s))
                 goto out;
             size += s;
        }
 
        Nptr = ((unsigned char *)list) + rlen;
-       for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) {
+       for (i = 0, nptr = (unsigned char *)any; i < ndevices; i++) {
            if (nptr >= Nptr)
                goto out;
            size += *nptr + 1;
@@ -244,10 +245,10 @@ XListInputDevices(
        }
        sclist = clist;
        Any = (XAnyClassPtr) ((char *)clist +
-                             (*ndevices * sizeof(XDeviceInfo)));
+                             (ndevices * sizeof(XDeviceInfo)));
        list = slist;
        any = sav_any;
-       for (i = 0; i < *ndevices; i++, list++, clist++) {
+       for (i = 0; i < ndevices; i++, list++, clist++) {
            clist->type = list->type;
            clist->id = list->id;
            clist->use = list->use;
@@ -260,7 +261,7 @@ XListInputDevices(
        clist = sclist;
        nptr = (unsigned char *)any;
        Nptr = (unsigned char *)Any;
-       for (i = 0; i < *ndevices; i++, clist++) {
+       for (i = 0; i < ndevices; i++, clist++) {
            clist->name = (char *)Nptr;
            memcpy(Nptr, nptr + 1, *nptr);
            Nptr += (*nptr);
@@ -269,6 +270,8 @@ XListInputDevices(
        }
     }
 
+    *ndevices_return = ndevices;
+
   out:
     XFree((char *)slist);
     UnlockDisplay(dpy);

commit acc71e232bcb95bce5e9d80113403ae16126dd6c
Author: Niels Ole Salscheider <niels_...@salscheider-online.de>
Date:   Fri Oct 7 21:46:44 2016 +0200

    SizeClassInfo can return 0 even without an error
    
    Catch the error case separately. Commit 19a9cd607d added length checking to
    SizeClassInfo but re-used the return value of 0 for an error. A device 
without
    classes (as is initialized by xf86-input-libinput for tablets) can
    legitimately return 0 and erroneously triggers an error.
    Fix this by using a separate value for the error.
    
    Reproducible by calling XListInputDevices() with a tablet attached.
    
    This fixes a regression introduced in commit 19a9cd607d.
    
    Signed-off-by: Niels Ole Salscheider <niels_...@salscheider-online.de>
    Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
    Reviewed-by: Emil Velikov <emil.l.veli...@gmail.com>

diff --git a/src/XListDev.c b/src/XListDev.c
index c74bfd1..45c16fe 100644
--- a/src/XListDev.c
+++ b/src/XListDev.c
@@ -73,27 +73,28 @@ static int pad_to_xid(int base_size)
     return ((base_size + padsize - 1)/padsize) * padsize;
 }
 
-static size_t
-SizeClassInfo(xAnyClassPtr *any, size_t len, int num_classes)
+static int
+SizeClassInfo(xAnyClassPtr *any, size_t len, int num_classes, size_t *size)
 {
-    int size = 0;
     int j;
+    size_t sz = 0;
+
     for (j = 0; j < num_classes; j++) {
         switch ((*any)->class) {
             case KeyClass:
-                size += pad_to_xid(sizeof(XKeyInfo));
+                sz += pad_to_xid(sizeof(XKeyInfo));
                 break;
             case ButtonClass:
-                size += pad_to_xid(sizeof(XButtonInfo));
+                sz += pad_to_xid(sizeof(XButtonInfo));
                 break;
             case ValuatorClass:
                 {
                     xValuatorInfoPtr v;
 
                     if (len < sizeof(v))
-                        return 0;
+                        return 1;
                     v = (xValuatorInfoPtr) *any;
-                    size += pad_to_xid(sizeof(XValuatorInfo) +
+                    sz += pad_to_xid(sizeof(XValuatorInfo) +
                         (v->num_axes * sizeof(XAxisInfo)));
                     break;
                 }
@@ -101,11 +102,13 @@ SizeClassInfo(xAnyClassPtr *any, size_t len, int 
num_classes)
                 break;
         }
         if ((*any)->length > len)
-            return 0;
+            return 1;
         *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
     }
 
-    return size;
+    *size = sz;
+
+    return 0;
 }
 
 static void
@@ -219,8 +222,7 @@ XListInputDevices(
        sav_any = any;
        end = (char *)list + rlen;
        for (i = 0; i < *ndevices; i++, list++) {
-            s = SizeClassInfo(&any, end - (char *)any, (int)list->num_classes);
-            if (!s)
+            if(SizeClassInfo(&any, end - (char *)any, (int)list->num_classes, 
&s))
                 goto out;
             size += s;
        }

commit 76c5a41fe2a209d8dba0c40c135b885ab0034d57
Author: Tobias Stoeckmann <tob...@stoeckmann.org>
Date:   Sun Sep 25 22:31:34 2016 +0200

    Properly validate server responses.
    
    By validating length fields from server responses, out of boundary
    accesses and endless loops can be mitigated.
    
    Signed-off-by: Tobias Stoeckmann <tob...@stoeckmann.org>
    Reviewed-by: Matthieu Herrb <matth...@herrb.eu>

diff --git a/src/XGMotion.c b/src/XGMotion.c
index a4c75b6..e0a0d36 100644
--- a/src/XGMotion.c
+++ b/src/XGMotion.c
@@ -114,7 +114,8 @@ XGetDeviceMotionEvents(
     }
     /* rep.axes is a CARD8, so assume max number of axes for bounds check */
     if (rep.nEvents <
-       (INT_MAX / (sizeof(XDeviceTimeCoord) + (UCHAR_MAX * sizeof(int))))) {
+       (INT_MAX / (sizeof(XDeviceTimeCoord) + (UCHAR_MAX * sizeof(int)))) &&
+       rep.nEvents * (rep.axes + 1) <= rep.length) {
        size_t bsize = rep.nEvents *
            (sizeof(XDeviceTimeCoord) + (rep.axes * sizeof(int)));
        bufp = Xmalloc(bsize);
diff --git a/src/XGetBMap.c b/src/XGetBMap.c
index 002daba..13bb8c6 100644
--- a/src/XGetBMap.c
+++ b/src/XGetBMap.c
@@ -92,7 +92,8 @@ XGetDeviceButtonMapping(
 
     status = _XReply(dpy, (xReply *) & rep, 0, xFalse);
     if (status == 1) {
-       if (rep.length <= (sizeof(mapping) >> 2)) {
+       if (rep.length <= (sizeof(mapping) >> 2) &&
+           rep.nElts <= (rep.length << 2)) {
            unsigned long nbytes = rep.length << 2;
            _XRead(dpy, (char *)mapping, nbytes);
 
diff --git a/src/XGetDCtl.c b/src/XGetDCtl.c
index 51ed0ae..a5efba2 100644
--- a/src/XGetDCtl.c
+++ b/src/XGetDCtl.c
@@ -93,7 +93,8 @@ XGetDeviceControl(
     if (rep.length > 0) {
        unsigned long nbytes;
        size_t size = 0;
-       if (rep.length < (INT_MAX >> 2)) {
+       if (rep.length < (INT_MAX >> 2) &&
+           (rep.length << 2) >= sizeof(xDeviceState)) {
            nbytes = (unsigned long) rep.length << 2;
            d = Xmalloc(nbytes);
        }
@@ -117,7 +118,8 @@ XGetDeviceControl(
            size_t val_size;
 
            r = (xDeviceResolutionState *) d;
-           if (r->num_valuators >= (INT_MAX / (3 * sizeof(int))))
+           if (sizeof(xDeviceResolutionState) > nbytes ||
+               r->num_valuators >= (INT_MAX / (3 * sizeof(int))))
                goto out;
            val_size = 3 * sizeof(int) * r->num_valuators;
            if ((sizeof(xDeviceResolutionState) + val_size) > nbytes)
diff --git a/src/XGetFCtl.c b/src/XGetFCtl.c
index 765efc9..d14bc10 100644
--- a/src/XGetFCtl.c
+++ b/src/XGetFCtl.c
@@ -73,6 +73,7 @@ XGetFeedbackControl(
     XFeedbackState *Sav = NULL;
     xFeedbackState *f = NULL;
     xFeedbackState *sav = NULL;
+    char *end = NULL;
     xGetFeedbackControlReq *req;
     xGetFeedbackControlReply rep;
     XExtDisplayInfo *info = XInput_find_display(dpy);
@@ -105,10 +106,12 @@ XGetFeedbackControl(
            goto out;
        }
        sav = f;
+       end = (char *)f + nbytes;
        _XRead(dpy, (char *)f, nbytes);
 
        for (i = 0; i < *num_feedbacks; i++) {
-           if (f->length > nbytes)
+           if ((char *)f + sizeof(*f) > end ||
+               f->length == 0 || f->length > nbytes)
                goto out;
            nbytes -= f->length;
 
@@ -128,6 +131,8 @@ XGetFeedbackControl(
 
                if (strf->num_syms_supported >= (INT_MAX / sizeof(KeySym)))
                    goto out;
+               if ((char *)f + sizeof(*strf) > end)
+                   goto out;
                size += sizeof(XStringFeedbackState) +
                    (strf->num_syms_supported * sizeof(KeySym));
            }
diff --git a/src/XGetKMap.c b/src/XGetKMap.c
index 00dde06..97ca179 100644
--- a/src/XGetKMap.c
+++ b/src/XGetKMap.c
@@ -54,6 +54,7 @@ SOFTWARE.
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/Xlibint.h>
@@ -93,9 +94,16 @@ XGetDeviceKeyMapping(register Display * dpy, XDevice * dev,
        return (KeySym *) NULL;
     }
     if (rep.length > 0) {
-       *syms_per_code = rep.keySymsPerKeyCode;
-       nbytes = (long)rep.length << 2;
-       mapping = (KeySym *) Xmalloc((unsigned)nbytes);
+       if (rep.length < INT_MAX >> 2 &&
+           rep.length == rep.keySymsPerKeyCode * keycount) {
+           *syms_per_code = rep.keySymsPerKeyCode;
+           nbytes = (long)rep.length << 2;
+           mapping = (KeySym *) Xmalloc((unsigned)nbytes);
+       } else {
+           *syms_per_code = 0;
+           nbytes = 0;
+           mapping = NULL;
+       }
        if (mapping)
            _XRead(dpy, (char *)mapping, nbytes);
        else
diff --git a/src/XGetMMap.c b/src/XGetMMap.c
index ce10c2d..a4418b4 100644
--- a/src/XGetMMap.c
+++ b/src/XGetMMap.c
@@ -53,6 +53,7 @@ SOFTWARE.
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/Xlibint.h>
@@ -85,8 +86,14 @@ XGetDeviceModifierMapping(
        SyncHandle();
        return (XModifierKeymap *) NULL;
     }
-    nbytes = (unsigned long)rep.length << 2;
-    res = (XModifierKeymap *) Xmalloc(sizeof(XModifierKeymap));
+    if (rep.length < (INT_MAX >> 2) &&
+       rep.numKeyPerModifier == rep.length >> 1) {
+       nbytes = (unsigned long)rep.length << 2;
+       res = (XModifierKeymap *) Xmalloc(sizeof(XModifierKeymap));
+    } else {
+       nbytes = 0;
+       res = NULL;
+    }
     if (res) {
        res->modifiermap = (KeyCode *) Xmalloc(nbytes);
        if (res->modifiermap)
diff --git a/src/XIQueryDevice.c b/src/XIQueryDevice.c
index 4be1eca..9a89430 100644
--- a/src/XIQueryDevice.c
+++ b/src/XIQueryDevice.c
@@ -26,6 +26,7 @@
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <stdint.h>
 #include <X11/Xlibint.h>
 #include <X11/extensions/XI2proto.h>
@@ -43,6 +44,7 @@ XIQueryDevice(Display *dpy, int deviceid, int 
*ndevices_return)
     xXIQueryDeviceReq   *req;
     xXIQueryDeviceReply reply;
     char                *ptr;
+    char                *end;
     int                 i;
     char                *buf;
 
@@ -60,14 +62,24 @@ XIQueryDevice(Display *dpy, int deviceid, int 
*ndevices_return)
     if (!_XReply(dpy, (xReply*) &reply, 0, xFalse))
         goto error;
 
-    *ndevices_return = reply.num_devices;
-    info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
+    if (reply.length < INT_MAX / 4)
+    {
+       *ndevices_return = reply.num_devices;
+       info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
+    }
+    else
+    {
+       *ndevices_return = 0;
+       info = NULL;
+    }
+
     if (!info)
         goto error;
 
     buf = Xmalloc(reply.length * 4);
     _XRead(dpy, buf, reply.length * 4);
     ptr = buf;
+    end = buf + reply.length * 4;
 
     /* info is a null-terminated array */
     info[reply.num_devices].name = NULL;
@@ -79,6 +91,9 @@ XIQueryDevice(Display *dpy, int deviceid, int 
*ndevices_return)
         XIDeviceInfo    *lib = &info[i];
         xXIDeviceInfo   *wire = (xXIDeviceInfo*)ptr;
 
+        if (ptr + sizeof(xXIDeviceInfo) > end)
+            goto error_loop;
+
         lib->deviceid    = wire->deviceid;
         lib->use         = wire->use;
         lib->attachment  = wire->attachment;
@@ -87,12 +102,23 @@ XIQueryDevice(Display *dpy, int deviceid, int 
*ndevices_return)
 
         ptr += sizeof(xXIDeviceInfo);
 
+        if (ptr + wire->name_len > end)
+            goto error_loop;
+
         lib->name = Xcalloc(wire->name_len + 1, 1);
+        if (lib->name == NULL)
+            goto error_loop;
         strncpy(lib->name, ptr, wire->name_len);
+        lib->name[wire->name_len] = '\0';
         ptr += ((wire->name_len + 3)/4) * 4;
 
         sz = size_classes((xXIAnyInfo*)ptr, nclasses);
         lib->classes = Xmalloc(sz);
+        if (lib->classes == NULL)
+        {
+            Xfree(lib->name);
+            goto error_loop;
+        }
         ptr += copy_classes(lib, (xXIAnyInfo*)ptr, &nclasses);
         /* We skip over unused classes */
         lib->num_classes = nclasses;
@@ -103,6 +129,12 @@ XIQueryDevice(Display *dpy, int deviceid, int 
*ndevices_return)
     SyncHandle();
     return info;
 
+error_loop:
+    while (--i >= 0)
+    {
+        Xfree(info[i].name);
+        Xfree(info[i].classes);
+    }
 error:
     UnlockDisplay(dpy);
     SyncHandle();
diff --git a/src/XListDev.c b/src/XListDev.c
index 8d0bdf6..c74bfd1 100644
--- a/src/XListDev.c
+++ b/src/XListDev.c
@@ -74,7 +74,7 @@ static int pad_to_xid(int base_size)
 }
 
 static size_t
-SizeClassInfo(xAnyClassPtr *any, int num_classes)
+SizeClassInfo(xAnyClassPtr *any, size_t len, int num_classes)
 {
     int size = 0;
     int j;
@@ -90,6 +90,8 @@ SizeClassInfo(xAnyClassPtr *any, int num_classes)
                 {
                     xValuatorInfoPtr v;
 
+                    if (len < sizeof(v))
+                        return 0;
                     v = (xValuatorInfoPtr) *any;
                     size += pad_to_xid(sizeof(XValuatorInfo) +
                         (v->num_axes * sizeof(XAxisInfo)));
@@ -98,6 +100,8 @@ SizeClassInfo(xAnyClassPtr *any, int num_classes)
             default:
                 break;
         }
+        if ((*any)->length > len)
+            return 0;
         *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
     }
 
@@ -169,7 +173,7 @@ XListInputDevices(
     register Display   *dpy,
     int                        *ndevices)
 {
-    size_t size;
+    size_t s, size;
     xListInputDevicesReq *req;
     xListInputDevicesReply rep;
     xDeviceInfo *list, *slist = NULL;
@@ -177,6 +181,7 @@ XListInputDevices(
     XDeviceInfo *clist = NULL;
     xAnyClassPtr any, sav_any;
     XAnyClassPtr Any;
+    char *end = NULL;
     unsigned char *nptr, *Nptr;
     int i;
     unsigned long rlen;
@@ -212,16 +217,20 @@ XListInputDevices(
 
        any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
        sav_any = any;
+       end = (char *)list + rlen;
        for (i = 0; i < *ndevices; i++, list++) {
-            size += SizeClassInfo(&any, (int)list->num_classes);
+            s = SizeClassInfo(&any, end - (char *)any, (int)list->num_classes);
+            if (!s)
+                goto out;
+            size += s;
        }
 
-       Nptr = ((unsigned char *)list) + rlen + 1;
+       Nptr = ((unsigned char *)list) + rlen;
        for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) {
+           if (nptr >= Nptr)
+               goto out;
            size += *nptr + 1;
            nptr += (*nptr + 1);
-           if (nptr > Nptr)
-               goto out;
        }
 
        clist = (XDeviceInfoPtr) Xmalloc(size);
diff --git a/src/XOpenDev.c b/src/XOpenDev.c
index e784f8b..848b8d2 100644
--- a/src/XOpenDev.c
+++ b/src/XOpenDev.c
@@ -53,6 +53,7 @@ SOFTWARE.
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/Xlibint.h>
@@ -86,9 +87,15 @@ XOpenDevice(
        return (XDevice *) NULL;
     }
 
-    rlen = rep.length << 2;
-    dev = (XDevice *) Xmalloc(sizeof(XDevice) + rep.num_classes *
-                             sizeof(XInputClassInfo));
+    if (rep.length < INT_MAX >> 2 &&
+       (rep.length << 2) >= rep.num_classes * sizeof(xInputClassInfo)) {
+       rlen = rep.length << 2;
+       dev = (XDevice *) Xmalloc(sizeof(XDevice) + rep.num_classes *
+                                 sizeof(XInputClassInfo));
+    } else {
+       rlen = 0;
+       dev = NULL;
+    }
     if (dev) {
        int dlen;       /* data length */
 
diff --git a/src/XQueryDv.c b/src/XQueryDv.c
index 3836777..ff26899 100644
--- a/src/XQueryDv.c
+++ b/src/XQueryDv.c
@@ -73,7 +73,7 @@ XQueryDeviceState(
     xQueryDeviceStateReply rep;
     XDeviceState *state = NULL;
     XInputClass *any, *Any;
-    char *data = NULL;
+    char *data = NULL, *end = NULL;
     XExtDisplayInfo *info = XInput_find_display(dpy);
 
     LockDisplay(dpy);
@@ -92,6 +92,7 @@ XQueryDeviceState(
        if (rep.length < (INT_MAX >> 2)) {
            rlen = (unsigned long) rep.length << 2;
            data = Xmalloc(rlen);
+           end = data + rlen;
        }
        if (!data) {
            _XEatDataWords(dpy, rep.length);
@@ -100,7 +101,8 @@ XQueryDeviceState(
        _XRead(dpy, data, rlen);
 
        for (i = 0, any = (XInputClass *) data; i < (int)rep.num_classes; i++) {
-           if (any->length > rlen)
+           if ((char *)any + sizeof(XInputClass) > end ||
+               any->length == 0 || any->length > rlen)
                goto out;
            rlen -= any->length;
 
@@ -114,6 +116,8 @@ XQueryDeviceState(
            case ValuatorClass:
            {
                xValuatorState *v = (xValuatorState *) any;
+               if ((char *)any + sizeof(xValuatorState) > end)
+                   goto out;
                size += (sizeof(XValuatorState) +
                         (v->num_valuators * sizeof(int)));
            }

Reply via email to