configure.ac        |    2 +-
 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 |   36 ++++++++++++++++++++++++++++++++++--
 src/XListDev.c      |   21 +++++++++++++++------
 src/XOpenDev.c      |   13 ++++++++++---
 src/XQueryDv.c      |    8 ++++++--
 11 files changed, 100 insertions(+), 24 deletions(-)

New commits:
commit 8e0476653dd134cee84f4e893f656b2f93c4e3b0
Author: Matthieu Herrb <matthieu.he...@laas.fr>
Date:   Tue Oct 4 21:14:01 2016 +0200

    libXi 1.7.7
    
    Signed-off-by: Matthieu Herrb <matthieu.he...@laas.fr>

diff --git a/configure.ac b/configure.ac
index 64033be..f7d322c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 
 # Initialize Autoconf
 AC_PREREQ([2.60])
-AC_INIT([libXi], [1.7.6],
+AC_INIT([libXi], [1.7.7],
        [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXi])
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_HEADERS([src/config.h])

commit 19a9cd607de73947fcfb104682f203ffe4e1f4e5
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 7785843..9433e29 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 c5d3b53..7f6b396 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 7fd6d0e..82dcc64 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;
 
@@ -125,6 +128,8 @@ XGetFeedbackControl(
            case StringFeedbackClass:
            {
                xStringFeedbackState *strf = (xStringFeedbackState *) f;
+               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 0540ce4..008a72b 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 246698c..33c114f 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 fb8504f..a457cd6 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);
 error_unlocked:
diff --git a/src/XListDev.c b/src/XListDev.c
index b85ff3c..f850cd0 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);
     }
 
@@ -170,7 +174,7 @@ XListInputDevices(
     register Display   *dpy,
     int                        *ndevices)
 {
-    size_t size;
+    size_t s, size;
     xListInputDevicesReq *req;
     xListInputDevicesReply rep;
     xDeviceInfo *list, *slist = NULL;
@@ -178,6 +182,7 @@ XListInputDevices(
     XDeviceInfo *clist = NULL;
     xAnyClassPtr any, sav_any;
     XAnyClassPtr Any;
+    char *end = NULL;
     unsigned char *nptr, *Nptr;
     int i;
     unsigned long rlen;
@@ -213,16 +218,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 029dec2..4b3c460 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 de1c0e5..7ee2272 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