open-src/lib/libXi/CVE-2013-19XX.patch
changeset 1345 d5dacbb8de2b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/lib/libXi/CVE-2013-19XX.patch	Wed May 15 13:44:02 2013 -0700
@@ -0,0 +1,1247 @@
+From bb82c72a1d69eaf60b7586570faf797df967f661 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Mon, 29 Apr 2013 18:39:34 -0700
+Subject: [PATCH:libXi] Expand comment on the memory vs. reply ordering in
+ XIGetSelectedEvents()
+
+Unpacking from the wire involves un-interleaving the structs & masks,
+which wasn't obvious to me the first time I read it, so make notes
+before I forget again.
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Signed-off-by: Peter Hutterer <[email protected]>
+---
+ src/XISelEv.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/src/XISelEv.c b/src/XISelEv.c
+index fa7eb54..f871222 100644
+--- a/src/XISelEv.c
++++ b/src/XISelEv.c
+@@ -135,8 +135,14 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
+ 
+     _XRead(dpy, (char*)mask_in, reply.length * 4);
+ 
+-    /* Memory layout of the XIEventMask for a 3 mask reply:
+-     * [struct a][struct b][struct c][masks a][masks b][masks c]
++    /*
++     * This function takes interleaved xXIEventMask structs & masks off
++     * the wire, such as this 3 mask reply:
++     *   [struct a][masks a][struct b][masks b][struct c][masks c]
++     * And generates a memory buffer to be returned to callers in which
++     * they are not interleaved, so that callers can treat the returned
++     * pointer as a simple array of XIEventMask structs, such as:
++     *   [struct a][struct b][struct c][masks a][masks b][masks c]
+      */
+     len = reply.num_masks * sizeof(XIEventMask);
+ 
+-- 
+1.7.9.2
+
+From 63841a81a340f1979cf5b0ffa1f7047dca988994 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Wed, 1 May 2013 23:58:39 -0700
+Subject: [PATCH:libXi 01/13] Use _XEatDataWords to avoid overflow of
+ rep.length bit shifting
+
+rep.length is a CARD32, so rep.length << 2 could overflow in 32-bit builds
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ configure.ac       |    6 ++++++
+ src/XGMotion.c     |    2 +-
+ src/XGetDCtl.c     |    2 +-
+ src/XGetDProp.c    |    5 ++---
+ src/XGetFCtl.c     |    2 +-
+ src/XGetKMap.c     |    2 +-
+ src/XGetMMap.c     |    2 +-
+ src/XGetProp.c     |    4 +---
+ src/XGtSelect.c    |    2 +-
+ src/XIProperties.c |    7 +++----
+ src/XIint.h        |   14 ++++++++++++++
+ src/XListDProp.c   |    2 +-
+ src/XListDev.c     |    2 +-
+ src/XOpenDev.c     |    2 +-
+ src/XQueryDv.c     |    2 +-
+ 15 files changed, 36 insertions(+), 20 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 8dbca38..f5ef1e2 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -31,6 +31,12 @@ PKG_CHECK_MODULES(XI, [xproto >= 7.0.13] [x11 >= 1.4.99.1] [xextproto >= 7.0.3]
+ # CFLAGS only for PointerBarrier typedef
+ PKG_CHECK_MODULES(XFIXES, [xfixes >= 5])
+ 
++# Check for _XEatDataWords function that may be patched into older Xlib releases
++SAVE_LIBS="$LIBS"
++LIBS="$XI_LIBS"
++AC_CHECK_FUNCS([_XEatDataWords])
++LIBS="$SAVE_LIBS"
++
+ # Check for xmlto and asciidoc for man page conversion
+ # (only needed by people building tarballs)
+ if test "$have_xmlto" = yes && test "$have_asciidoc" = yes; then
+diff --git a/src/XGMotion.c b/src/XGMotion.c
+index 99b1c44..5feac85 100644
+--- a/src/XGMotion.c
++++ b/src/XGMotion.c
+@@ -112,7 +112,7 @@ XGetDeviceMotionEvents(
+ 	Xfree(bufp);
+ 	Xfree(savp);
+ 	*nEvents = 0;
+-	_XEatData(dpy, (unsigned long)size);
++	_XEatDataWords(dpy, rep.length);
+ 	UnlockDisplay(dpy);
+ 	SyncHandle();
+ 	return (NULL);
+diff --git a/src/XGetDCtl.c b/src/XGetDCtl.c
+index c66212d..f73a4e8 100644
+--- a/src/XGetDCtl.c
++++ b/src/XGetDCtl.c
+@@ -95,7 +95,7 @@ XGetDeviceControl(
+ 	nbytes = (long)rep.length << 2;
+ 	d = (xDeviceState *) Xmalloc((unsigned)nbytes);
+ 	if (!d) {
+-	    _XEatData(dpy, (unsigned long)nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	    goto out;
+ 	}
+ 	sav = d;
+diff --git a/src/XGetDProp.c b/src/XGetDProp.c
+index 5d44f91..f9e8f0c 100644
+--- a/src/XGetDProp.c
++++ b/src/XGetDProp.c
+@@ -112,14 +112,13 @@ XGetDeviceProperty(Display* dpy, XDevice* dev,
+ 	     * This part of the code should never be reached.  If it is,
+ 	     * the server sent back a property with an invalid format.
+ 	     */
+-	    nbytes = rep.length << 2;
+-	    _XEatData(dpy, (unsigned long) nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	    UnlockDisplay(dpy);
+ 	    SyncHandle();
+ 	    return(BadImplementation);
+ 	}
+ 	if (! *prop) {
+-	    _XEatData(dpy, (unsigned long) nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	    UnlockDisplay(dpy);
+ 	    SyncHandle();
+ 	    return(BadAlloc);
+diff --git a/src/XGetFCtl.c b/src/XGetFCtl.c
+index 43afa00..28fab4d 100644
+--- a/src/XGetFCtl.c
++++ b/src/XGetFCtl.c
+@@ -95,7 +95,7 @@ XGetFeedbackControl(
+ 	nbytes = (long)rep.length << 2;
+ 	f = (xFeedbackState *) Xmalloc((unsigned)nbytes);
+ 	if (!f) {
+-	    _XEatData(dpy, (unsigned long)nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	    goto out;
+ 	}
+ 	sav = f;
+diff --git a/src/XGetKMap.c b/src/XGetKMap.c
+index 9431fbb..00dde06 100644
+--- a/src/XGetKMap.c
++++ b/src/XGetKMap.c
+@@ -99,7 +99,7 @@ XGetDeviceKeyMapping(register Display * dpy, XDevice * dev,
+ 	if (mapping)
+ 	    _XRead(dpy, (char *)mapping, nbytes);
+ 	else
+-	    _XEatData(dpy, (unsigned long)nbytes);
++	    _XEatDataWords(dpy, rep.length);
+     }
+ 
+     UnlockDisplay(dpy);
+diff --git a/src/XGetMMap.c b/src/XGetMMap.c
+index 8a1cdb2..ce10c2d 100644
+--- a/src/XGetMMap.c
++++ b/src/XGetMMap.c
+@@ -92,7 +92,7 @@ XGetDeviceModifierMapping(
+ 	if (res->modifiermap)
+ 	    _XReadPad(dpy, (char *)res->modifiermap, nbytes);
+ 	else
+-	    _XEatData(dpy, (unsigned long)nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	res->max_keypermod = rep.numKeyPerModifier;
+     }
+ 
+diff --git a/src/XGetProp.c b/src/XGetProp.c
+index c5d088b..34bc581 100644
+--- a/src/XGetProp.c
++++ b/src/XGetProp.c
+@@ -68,7 +68,6 @@ XGetDeviceDontPropagateList(
+     int			*count)
+ {
+     XEventClass *list = NULL;
+-    int rlen;
+     xGetDeviceDontPropagateListReq *req;
+     xGetDeviceDontPropagateListReply rep;
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+@@ -90,7 +89,6 @@ XGetDeviceDontPropagateList(
+     *count = rep.count;
+ 
+     if (*count) {
+-	rlen = rep.length << 2;
+ 	list = (XEventClass *) Xmalloc(rep.length * sizeof(XEventClass));
+ 	if (list) {
+ 	    int i;
+@@ -105,7 +103,7 @@ XGetDeviceDontPropagateList(
+ 		list[i] = (XEventClass) ec;
+ 	    }
+ 	} else
+-	    _XEatData(dpy, (unsigned long)rlen);
++	    _XEatDataWords(dpy, rep.length);
+     }
+ 
+     UnlockDisplay(dpy);
+diff --git a/src/XGtSelect.c b/src/XGtSelect.c
+index f890db7..5c0f812 100644
+--- a/src/XGtSelect.c
++++ b/src/XGtSelect.c
+@@ -104,7 +104,7 @@ XGetSelectedExtensionEvents(
+ 		(XEventClass *) Xmalloc(*this_client_count *
+ 					sizeof(XEventClass));
+ 	    if (!*this_client_list) {
+-		_XEatData(dpy, (unsigned long)tlen + alen);
++		_XEatDataWords(dpy, rep.length);
+                 UnlockDisplay(dpy);
+                 SyncHandle();
+ 		return (Success);
+diff --git a/src/XIProperties.c b/src/XIProperties.c
+index 83a7a68..5e58fb6 100644
+--- a/src/XIProperties.c
++++ b/src/XIProperties.c
+@@ -64,7 +64,7 @@ XIListProperties(Display* dpy, int deviceid, int *num_props_return)
+         props = (Atom*)Xmalloc(rep.num_properties * sizeof(Atom));
+         if (!props)
+         {
+-            _XEatData(dpy, rep.num_properties << 2);
++            _XEatDataWords(dpy, rep.length);
+             goto cleanup;
+         }
+ 
+@@ -203,8 +203,7 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset,
+ 	     * This part of the code should never be reached.  If it is,
+ 	     * the server sent back a property with an invalid format.
+ 	     */
+-	    nbytes = rep.length << 2;
+-	    _XEatData(dpy, nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	    UnlockDisplay(dpy);
+ 	    SyncHandle();
+ 	    return(BadImplementation);
+@@ -222,7 +221,7 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset,
+         *data = Xmalloc(rbytes);
+ 
+ 	if (!(*data)) {
+-	    _XEatData(dpy, nbytes);
++	    _XEatDataWords(dpy, rep.length);
+ 	    UnlockDisplay(dpy);
+ 	    SyncHandle();
+ 	    return(BadAlloc);
+diff --git a/src/XIint.h b/src/XIint.h
+index 571bb23..3ddc3c5 100644
+--- a/src/XIint.h
++++ b/src/XIint.h
+@@ -83,4 +83,18 @@ next_block(void **ptr, int size) {
+     return ret;
+ }
+ 
++#ifndef HAVE__XEATDATAWORDS
++#include <X11/Xmd.h>  /* for LONG64 on 64-bit platforms */
++#include <limits.h>
++
++static inline void _XEatDataWords(Display *dpy, unsigned long n)
++{
++# ifndef LONG64
++    if (n >= (ULONG_MAX >> 2))
++        _XIOError(dpy);
++# endif
++    _XEatData (dpy, n << 2);
++}
++#endif
++
+ #endif
+diff --git a/src/XListDProp.c b/src/XListDProp.c
+index 8667350..bde6cb5 100644
+--- a/src/XListDProp.c
++++ b/src/XListDProp.c
+@@ -65,7 +65,7 @@ XListDeviceProperties(Display* dpy, XDevice* dev, int *nprops_return)
+         props = (Atom*)Xmalloc(rep.nAtoms * sizeof(Atom));
+         if (!props)
+         {
+-            _XEatData(dpy, rep.nAtoms << 2);
++            _XEatDataWords(dpy, rep.length);
+             goto cleanup;
+         }
+ 
+diff --git a/src/XListDev.c b/src/XListDev.c
+index bd6e70a..1fa4747 100644
+--- a/src/XListDev.c
++++ b/src/XListDev.c
+@@ -202,7 +202,7 @@ XListInputDevices(
+ 	list = (xDeviceInfo *) Xmalloc(rlen);
+ 	slist = list;
+ 	if (!slist) {
+-	    _XEatData(dpy, (unsigned long)rlen);
++	    _XEatDataWords(dpy, rep.length);
+ 	    UnlockDisplay(dpy);
+ 	    SyncHandle();
+ 	    return (XDeviceInfo *) NULL;
+diff --git a/src/XOpenDev.c b/src/XOpenDev.c
+index 74f18ac..e784f8b 100644
+--- a/src/XOpenDev.c
++++ b/src/XOpenDev.c
+@@ -101,7 +101,7 @@ XOpenDevice(
+ 	if (rlen - dlen > 0)
+ 	    _XEatData(dpy, (unsigned long)rlen - dlen);
+     } else
+-	_XEatData(dpy, (unsigned long)rlen);
++	_XEatDataWords(dpy, rep.length);
+ 
+     UnlockDisplay(dpy);
+     SyncHandle();
+diff --git a/src/XQueryDv.c b/src/XQueryDv.c
+index 24d4e4e..69c285b 100644
+--- a/src/XQueryDv.c
++++ b/src/XQueryDv.c
+@@ -91,7 +91,7 @@ XQueryDeviceState(
+     if (rlen > 0) {
+ 	data = Xmalloc(rlen);
+ 	if (!data) {
+-	    _XEatData(dpy, (unsigned long)rlen);
++	    _XEatDataWords(dpy, rep.length);
+ 	    goto out;
+ 	}
+ 	_XRead(dpy, data, rlen);
+-- 
+1.7.9.2
+
+From 0acd07e1c9583e2e7c26c13f8628bde992d9bce5 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:26:52 -0800
+Subject: [PATCH:libXi 02/13] Stack buffer overflow in
+ XGetDeviceButtonMapping() [CVE-2013-1998 1/3]
+
+We copy the entire reply sent by the server into the fixed size
+mapping[] array on the stack, even if the server says it's a larger
+size than the mapping array can hold.  HULK SMASH STACK!
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XGetBMap.c |   21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/src/XGetBMap.c b/src/XGetBMap.c
+index 211c9ca..002daba 100644
+--- a/src/XGetBMap.c
++++ b/src/XGetBMap.c
+@@ -60,6 +60,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ #ifdef MIN	/* some systems define this in <sys/param.h> */
+ #undef MIN
+@@ -75,7 +76,6 @@ XGetDeviceButtonMapping(
+ {
+     int status = 0;
+     unsigned char mapping[256];	/* known fixed size */
+-    long nbytes;
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+ 
+     register xGetDeviceButtonMappingReq *req;
+@@ -92,13 +92,18 @@ XGetDeviceButtonMapping(
+ 
+     status = _XReply(dpy, (xReply *) & rep, 0, xFalse);
+     if (status == 1) {
+-	nbytes = (long)rep.length << 2;
+-	_XRead(dpy, (char *)mapping, nbytes);
+-
+-	/* don't return more data than the user asked for. */
+-	if (rep.nElts)
+-	    memcpy((char *)map, (char *)mapping, MIN((int)rep.nElts, nmap));
+-	status = rep.nElts;
++	if (rep.length <= (sizeof(mapping) >> 2)) {
++	    unsigned long nbytes = rep.length << 2;
++	    _XRead(dpy, (char *)mapping, nbytes);
++
++	    /* don't return more data than the user asked for. */
++	    if (rep.nElts)
++		memcpy(map, mapping, MIN((int)rep.nElts, nmap));
++	    status = rep.nElts;
++	} else {
++	    _XEatDataWords(dpy, rep.length);
++	    status = 0;
++	}
+     } else
+ 	status = 0;
+     UnlockDisplay(dpy);
+-- 
+1.7.9.2
+
+From 18855aa8c261863c00690b7df1e5ce4660687fb6 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 23:37:23 -0800
+Subject: [PATCH:libXi 03/13] memory corruption in _XIPassiveGrabDevice()
+ [CVE-2013-1998 2/3]
+
+If the server returned more modifiers than the caller asked for,
+we'd just keep copying past the end of the array provided by the
+caller, writing over who-knows-what happened to be there.
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XIPassiveGrab.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/XIPassiveGrab.c b/src/XIPassiveGrab.c
+index ac17c01..53b4084 100644
+--- a/src/XIPassiveGrab.c
++++ b/src/XIPassiveGrab.c
+@@ -88,7 +88,7 @@ _XIPassiveGrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
+         return -1;
+     _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo));
+ 
+-    for (i = 0; i < reply.num_modifiers; i++)
++    for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++)
+     {
+         modifiers_inout[i].status = failed_mods[i].status;
+         modifiers_inout[i].modifiers = failed_mods[i].modifiers;
+-- 
+1.7.9.2
+
+From a74690ba880036e01fc39f522b7567daf3746a31 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 26 Apr 2013 22:48:36 -0700
+Subject: [PATCH:libXi 04/13] unvalidated lengths in XQueryDeviceState()
+ [CVE-2013-1998 3/3]
+
+If the lengths given for each class state in the reply add up to more
+than the rep.length, we could read past the end of the buffer allocated
+to hold the data read from the server.
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XQueryDv.c |   17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/src/XQueryDv.c b/src/XQueryDv.c
+index 69c285b..3836777 100644
+--- a/src/XQueryDv.c
++++ b/src/XQueryDv.c
+@@ -59,6 +59,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ XDeviceState *
+ XQueryDeviceState(
+@@ -66,8 +67,8 @@ XQueryDeviceState(
+     XDevice		*dev)
+ {
+     int i, j;
+-    int rlen;
+-    int size = 0;
++    unsigned long rlen;
++    size_t size = 0;
+     xQueryDeviceStateReq *req;
+     xQueryDeviceStateReply rep;
+     XDeviceState *state = NULL;
+@@ -87,9 +88,11 @@ XQueryDeviceState(
+     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse))
+         goto out;
+ 
+-    rlen = rep.length << 2;
+-    if (rlen > 0) {
+-	data = Xmalloc(rlen);
++    if (rep.length > 0) {
++	if (rep.length < (INT_MAX >> 2)) {
++	    rlen = (unsigned long) rep.length << 2;
++	    data = Xmalloc(rlen);
++	}
+ 	if (!data) {
+ 	    _XEatDataWords(dpy, rep.length);
+ 	    goto out;
+@@ -97,6 +100,10 @@ XQueryDeviceState(
+ 	_XRead(dpy, data, rlen);
+ 
+ 	for (i = 0, any = (XInputClass *) data; i < (int)rep.num_classes; i++) {
++	    if (any->length > rlen)
++		goto out;
++	    rlen -= any->length;
++
+ 	    switch (any->class) {
+ 	    case KeyClass:
+ 		size += sizeof(XKeyState);
+-- 
+1.7.9.2
+
+From 38b563078ee050086526294f42f9f162be4bf97d Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:55:23 -0800
+Subject: [PATCH:libXi 05/13] integer overflow in XGetDeviceControl()
+ [CVE-2013-1984 1/8]
+
+If the number of valuators reported by the server is large enough that
+it overflows when multiplied by the size of the appropriate struct, then
+memory corruption can occur when more bytes are copied from the X server
+reply than the size of the buffer we allocated to hold them.
+
+v2: check that reply size fits inside the data read from the server, so
+we don't read out of bounds either
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XGetDCtl.c |   31 ++++++++++++++++++++++++-------
+ 1 file changed, 24 insertions(+), 7 deletions(-)
+
+diff --git a/src/XGetDCtl.c b/src/XGetDCtl.c
+index f73a4e8..51ed0ae 100644
+--- a/src/XGetDCtl.c
++++ b/src/XGetDCtl.c
+@@ -61,6 +61,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ XDeviceControl *
+ XGetDeviceControl(
+@@ -68,8 +69,6 @@ XGetDeviceControl(
+     XDevice		*dev,
+     int			 control)
+ {
+-    int size = 0;
+-    int nbytes, i;
+     XDeviceControl *Device = NULL;
+     XDeviceControl *Sav = NULL;
+     xDeviceState *d = NULL;
+@@ -92,8 +91,12 @@ XGetDeviceControl(
+ 	goto out;
+ 
+     if (rep.length > 0) {
+-	nbytes = (long)rep.length << 2;
+-	d = (xDeviceState *) Xmalloc((unsigned)nbytes);
++	unsigned long nbytes;
++	size_t size = 0;
++	if (rep.length < (INT_MAX >> 2)) {
++	    nbytes = (unsigned long) rep.length << 2;
++	    d = Xmalloc(nbytes);
++	}
+ 	if (!d) {
+ 	    _XEatDataWords(dpy, rep.length);
+ 	    goto out;
+@@ -111,33 +114,46 @@ XGetDeviceControl(
+ 	case DEVICE_RESOLUTION:
+ 	{
+ 	    xDeviceResolutionState *r;
++	    size_t val_size;
+ 
+ 	    r = (xDeviceResolutionState *) d;
+-	    size += sizeof(XDeviceResolutionState) +
+-		(3 * sizeof(int) * r->num_valuators);
++	    if (r->num_valuators >= (INT_MAX / (3 * sizeof(int))))
++		goto out;
++	    val_size = 3 * sizeof(int) * r->num_valuators;
++	    if ((sizeof(xDeviceResolutionState) + val_size) > nbytes)
++		goto out;
++	    size += sizeof(XDeviceResolutionState) + val_size;
+ 	    break;
+ 	}
+         case DEVICE_ABS_CALIB:
+         {
++            if (sizeof(xDeviceAbsCalibState) > nbytes)
++                goto out;
+             size += sizeof(XDeviceAbsCalibState);
+             break;
+         }
+         case DEVICE_ABS_AREA:
+         {
++            if (sizeof(xDeviceAbsAreaState) > nbytes)
++                goto out;
+             size += sizeof(XDeviceAbsAreaState);
+             break;
+         }
+         case DEVICE_CORE:
+         {
++            if (sizeof(xDeviceCoreState) > nbytes)
++                goto out;
+             size += sizeof(XDeviceCoreState);
+             break;
+         }
+ 	default:
++	    if (d->length > nbytes)
++		goto out;
+ 	    size += d->length;
+ 	    break;
+ 	}
+ 
+-	Device = (XDeviceControl *) Xmalloc((unsigned)size);
++	Device = Xmalloc(size);
+ 	if (!Device)
+ 	    goto out;
+ 
+@@ -150,6 +166,7 @@ XGetDeviceControl(
+ 	    int *iptr, *iptr2;
+ 	    xDeviceResolutionState *r;
+ 	    XDeviceResolutionState *R;
++	    unsigned int i;
+ 
+ 	    r = (xDeviceResolutionState *) d;
+ 	    R = (XDeviceResolutionState *) Device;
+-- 
+1.7.9.2
+
+From 9e39ad6e66a517c2324426c3aa32f4cfcc1cd4f5 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:55:23 -0800
+Subject: [PATCH:libXi 06/13] integer overflow in XGetFeedbackControl()
+ [CVE-2013-1984 2/8]
+
+If the number of feedbacks reported by the server is large enough that
+it overflows when multiplied by the size of the appropriate struct, or
+if the total size of all the feedback structures overflows when added
+together, then memory corruption can occur when more bytes are copied from
+the X server reply than the size of the buffer we allocated to hold them.
+
+v2: check that reply size fits inside the data read from the server, so
+    we don't read out of bounds either
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XGetFCtl.c |   24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/src/XGetFCtl.c b/src/XGetFCtl.c
+index 28fab4d..bb50bf3 100644
+--- a/src/XGetFCtl.c
++++ b/src/XGetFCtl.c
+@@ -61,6 +61,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ XFeedbackState *
+ XGetFeedbackControl(
+@@ -68,8 +69,6 @@ XGetFeedbackControl(
+     XDevice		*dev,
+     int			*num_feedbacks)
+ {
+-    int size = 0;
+-    int nbytes, i;
+     XFeedbackState *Feedback = NULL;
+     XFeedbackState *Sav = NULL;
+     xFeedbackState *f = NULL;
+@@ -91,9 +90,16 @@ XGetFeedbackControl(
+ 	goto out;
+ 
+     if (rep.length > 0) {
++	unsigned long nbytes;
++	size_t size = 0;
++	int i;
++
+ 	*num_feedbacks = rep.num_feedbacks;
+-	nbytes = (long)rep.length << 2;
+-	f = (xFeedbackState *) Xmalloc((unsigned)nbytes);
++
++	if (rep.length < (INT_MAX >> 2)) {
++	    nbytes = rep.length << 2;
++	    f = Xmalloc(nbytes);
++	}
+ 	if (!f) {
+ 	    _XEatDataWords(dpy, rep.length);
+ 	    goto out;
+@@ -102,6 +108,10 @@ XGetFeedbackControl(
+ 	_XRead(dpy, (char *)f, nbytes);
+ 
+ 	for (i = 0; i < *num_feedbacks; i++) {
++	    if (f->length > nbytes)
++		goto out;
++	    nbytes -= f->length;
++
+ 	    switch (f->class) {
+ 	    case KbdFeedbackClass:
+ 		size += sizeof(XKbdFeedbackState);
+@@ -116,6 +126,8 @@ XGetFeedbackControl(
+ 	    {
+ 		xStringFeedbackState *strf = (xStringFeedbackState *) f;
+ 
++		if (strf->num_syms_supported >= (INT_MAX / sizeof(KeySym)))
++		    goto out;
+ 		size += sizeof(XStringFeedbackState) +
+ 		    (strf->num_syms_supported * sizeof(KeySym));
+ 	    }
+@@ -130,10 +142,12 @@ XGetFeedbackControl(
+ 		size += f->length;
+ 		break;
+ 	    }
++	    if (size > INT_MAX)
++		goto out;
+ 	    f = (xFeedbackState *) ((char *)f + f->length);
+ 	}
+ 
+-	Feedback = (XFeedbackState *) Xmalloc((unsigned)size);
++	Feedback = Xmalloc(size);
+ 	if (!Feedback)
+ 	    goto out;
+ 
+-- 
+1.7.9.2
+
+From 0bb14773ba37dfa8098b3e1784c80658019f9f21 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:55:23 -0800
+Subject: [PATCH:libXi 07/13] integer overflow in
+ XGetDeviceDontPropagateList() [CVE-2013-1984
+ 3/8]
+
+If the number of event classes reported by the server is large enough
+that it overflows when multiplied by the size of the appropriate struct,
+then memory corruption can occur when more bytes are copied from the
+X server reply than the size of the buffer we allocated to hold them.
+
+V2: EatData if count is 0 but length is > 0 to avoid XIOErrors
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XGetProp.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/XGetProp.c b/src/XGetProp.c
+index 34bc581..b49328c 100644
+--- a/src/XGetProp.c
++++ b/src/XGetProp.c
+@@ -60,6 +60,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ XEventClass *
+ XGetDeviceDontPropagateList(
+@@ -88,10 +89,11 @@ XGetDeviceDontPropagateList(
+     }
+     *count = rep.count;
+ 
+-    if (*count) {
+-	list = (XEventClass *) Xmalloc(rep.length * sizeof(XEventClass));
++    if (rep.length != 0) {
++	if ((rep.count != 0) && (rep.length < (INT_MAX / sizeof(XEventClass))))
++	    list = Xmalloc(rep.length * sizeof(XEventClass));
+ 	if (list) {
+-	    int i;
++	    unsigned int i;
+ 	    CARD32 ec;
+ 
+ 	    /* read and assign each XEventClass separately because
+-- 
+1.7.9.2
+
+From 3d1fc7cd03e9a41b86cd83a8922df551a1b87179 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:55:23 -0800
+Subject: [PATCH:libXi 08/13] integer overflow in XGetDeviceMotionEvents()
+ [CVE-2013-1984 4/8]
+
+If the number of events or axes reported by the server is large enough
+that it overflows when multiplied by the size of the appropriate struct,
+then memory corruption can occur when more bytes are copied from the
+X server reply than the size of the buffer we allocated to hold them.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XGMotion.c |   22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/src/XGMotion.c b/src/XGMotion.c
+index 5feac85..a4c75b6 100644
+--- a/src/XGMotion.c
++++ b/src/XGMotion.c
+@@ -59,6 +59,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ XDeviceTimeCoord *
+ XGetDeviceMotionEvents(
+@@ -74,7 +75,7 @@ XGetDeviceMotionEvents(
+     xGetDeviceMotionEventsReply rep;
+     XDeviceTimeCoord *tc;
+     int *data, *bufp, *readp, *savp;
+-    long size, size2;
++    unsigned long size;
+     int i, j;
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+ 
+@@ -104,10 +105,21 @@ XGetDeviceMotionEvents(
+ 	SyncHandle();
+ 	return (NULL);
+     }
+-    size = rep.length << 2;
+-    size2 = rep.nEvents * (sizeof(XDeviceTimeCoord) + (rep.axes * sizeof(int)));
+-    savp = readp = (int *)Xmalloc(size);
+-    bufp = (int *)Xmalloc(size2);
++    if (rep.length < (INT_MAX >> 2)) {
++	size = rep.length << 2;
++	savp = readp = Xmalloc(size);
++    } else {
++	size = 0;
++	savp = readp = NULL;
++    }
++    /* 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))))) {
++	size_t bsize = rep.nEvents *
++	    (sizeof(XDeviceTimeCoord) + (rep.axes * sizeof(int)));
++	bufp = Xmalloc(bsize);
++    } else
++	bufp = NULL;
+     if (!bufp || !savp) {
+ 	Xfree(bufp);
+ 	Xfree(savp);
+-- 
+1.7.9.2
+
+From 1202a8fc208581e184d327118a8a8ac3a27bbe64 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:55:23 -0800
+Subject: [PATCH:libXi 09/13] integer overflow in XIGetProperty()
+ [CVE-2013-1984 5/8]
+
+If the number of items reported by the server is large enough that
+it overflows when multiplied by the size of the appropriate item type,
+then memory corruption can occur when more bytes are copied from the
+X server reply than the size of the buffer we allocated to hold them.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XIProperties.c |   11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/XIProperties.c b/src/XIProperties.c
+index 5e58fb6..32436d1 100644
+--- a/src/XIProperties.c
++++ b/src/XIProperties.c
+@@ -38,6 +38,7 @@
+ #include <X11/extensions/XInput2.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ Atom*
+ XIListProperties(Display* dpy, int deviceid, int *num_props_return)
+@@ -170,7 +171,7 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset,
+ {
+     xXIGetPropertyReq   *req;
+     xXIGetPropertyReply rep;
+-    long                    nbytes, rbytes;
++    unsigned long       nbytes, rbytes;
+ 
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+ 
+@@ -216,9 +217,11 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset,
+ 	 * recopy the string to make it null terminated.
+ 	 */
+ 
+-        nbytes = rep.num_items * rep.format/8;
+-        rbytes = nbytes + 1;
+-        *data = Xmalloc(rbytes);
++	if (rep.num_items < (INT_MAX / (rep.format/8))) {
++	    nbytes = rep.num_items * rep.format/8;
++	    rbytes = nbytes + 1;
++	    *data = Xmalloc(rbytes);
++	}
+ 
+ 	if (!(*data)) {
+ 	    _XEatDataWords(dpy, rep.length);
+-- 
+1.7.9.2
+
+From a3e76afd699b7afa590c8d3567663460c9870924 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 22:55:23 -0800
+Subject: [PATCH:libXi 10/13] integer overflow in XIGetSelectedEvents()
+ [CVE-2013-1984 6/8]
+
+If the number of events or masks reported by the server is large enough
+that it overflows when multiplied by the size of the appropriate struct,
+or the sizes overflow as they are totaled up, then memory corruption can
+occur when more bytes are copied from the X server reply than the size
+of the buffer we allocated to hold them.
+
+v2: check that reply size fits inside the data read from the server,
+    so that we don't read out of bounds either
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XISelEv.c |   25 +++++++++++++++++++------
+ 1 file changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/src/XISelEv.c b/src/XISelEv.c
+index f871222..0471bef 100644
+--- a/src/XISelEv.c
++++ b/src/XISelEv.c
+@@ -42,6 +42,7 @@ in this Software without prior written authorization from the author.
+ #include <X11/extensions/ge.h>
+ #include <X11/extensions/geproto.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ int
+ XISelectEvents(Display* dpy, Window win, XIEventMask* masks, int num_masks)
+@@ -101,13 +102,14 @@ out:
+ XIEventMask*
+ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
+ {
+-    int i, len = 0;
++    unsigned int i, len = 0;
+     unsigned char *mask;
+     XIEventMask *mask_out = NULL;
+     xXIEventMask *mask_in = NULL, *mi;
+     xXIGetSelectedEventsReq *req;
+     xXIGetSelectedEventsReply reply;
+     XExtDisplayInfo *info = XInput_find_display(dpy);
++    size_t rbytes;
+ 
+     *num_masks_return = -1;
+     LockDisplay(dpy);
+@@ -129,11 +131,16 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
+         goto out;
+     }
+ 
+-    mask_in = Xmalloc(reply.length * 4);
+-    if (!mask_in)
++    if (reply.length < (INT_MAX >> 2)) {
++        rbytes = (unsigned long) reply.length << 2;
++        mask_in = Xmalloc(rbytes);
++    }
++    if (!mask_in) {
++        _XEatDataWords(dpy, reply.length);
+         goto out;
++    }
+ 
+-    _XRead(dpy, (char*)mask_in, reply.length * 4);
++    _XRead(dpy, (char*)mask_in, rbytes);
+ 
+     /*
+      * This function takes interleaved xXIEventMask structs & masks off
+@@ -148,8 +155,14 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
+ 
+     for (i = 0, mi = mask_in; i < reply.num_masks; i++)
+     {
+-        len += mi->mask_len * 4;
+-        mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4);
++        unsigned int mask_bytes = mi->mask_len * 4;
++        len += mask_bytes;
++        if (len > INT_MAX)
++            goto out;
++        if ((sizeof(xXIEventMask) + mask_bytes) > rbytes)
++            goto out;
++        rbytes -= (sizeof(xXIEventMask) + mask_bytes);
++        mi = (xXIEventMask*)((char*)mi + mask_bytes);
+         mi++;
+     }
+ 
+-- 
+1.7.9.2
+
+From b6246afd838842d28ac94d901507390624f31c7d Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sun, 10 Mar 2013 13:30:55 -0700
+Subject: [PATCH:libXi 11/13] Avoid integer overflow in XGetDeviceProperties()
+ [CVE-2013-1984 7/8]
+
+If the number of items as reported by the Xserver is too large, it
+could overflow the calculation for the size of the buffer to copy the
+reply into, causing memory corruption.
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XGetDProp.c |   61 +++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 37 insertions(+), 24 deletions(-)
+
+diff --git a/src/XGetDProp.c b/src/XGetDProp.c
+index f9e8f0c..3691122 100644
+--- a/src/XGetDProp.c
++++ b/src/XGetDProp.c
+@@ -38,6 +38,7 @@ in this Software without prior written authorization from the author.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ int
+ XGetDeviceProperty(Display* dpy, XDevice* dev,
+@@ -48,7 +49,8 @@ XGetDeviceProperty(Display* dpy, XDevice* dev,
+ {
+     xGetDevicePropertyReq   *req;
+     xGetDevicePropertyReply rep;
+-    long                    nbytes, rbytes;
++    unsigned long           nbytes, rbytes;
++    int                     ret = Success;
+ 
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+ 
+@@ -81,30 +83,43 @@ XGetDeviceProperty(Display* dpy, XDevice* dev,
+ 	 * data, but this last byte is null terminated and convenient for
+ 	 * returning string properties, so the client doesn't then have to
+ 	 * recopy the string to make it null terminated.
++	 *
++	 * Maximum item limits are set to both prevent integer overflow when
++	 * calculating the amount of memory to malloc, and to limit how much
++	 * memory will be used if a server provides an insanely high count.
+ 	 */
+ 	switch (rep.format) {
+ 	case 8:
+-	    nbytes = rep.nItems;
+-	    rbytes = rep.nItems + 1;
+-	    if (rbytes > 0 &&
+-		(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
+-		_XReadPad (dpy, (char *) *prop, nbytes);
++	    if (rep.nItems < INT_MAX) {
++		nbytes = rep.nItems;
++		rbytes = rep.nItems + 1;
++		if ((*prop = Xmalloc (rbytes)))
++		    _XReadPad (dpy, (char *) *prop, nbytes);
++		else
++		    ret = BadAlloc;
++	    }
+ 	    break;
+ 
+ 	case 16:
+-	    nbytes = rep.nItems << 1;
+-	    rbytes = rep.nItems * sizeof (short) + 1;
+-	    if (rbytes > 0 &&
+-		(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
+-		_XRead16Pad (dpy, (short *) *prop, nbytes);
++	    if (rep.nItems < (INT_MAX / sizeof (short))) {
++		nbytes = rep.nItems << 1;
++		rbytes = rep.nItems * sizeof (short) + 1;
++		if ((*prop = Xmalloc (rbytes)))
++		    _XRead16Pad (dpy, (short *) *prop, nbytes);
++		else
++		    ret = BadAlloc;
++	    }
+ 	    break;
+ 
+ 	case 32:
+-	    nbytes = rep.nItems << 2;
+-	    rbytes = rep.nItems * sizeof (long) + 1;
+-	    if (rbytes > 0 &&
+-		(*prop = (unsigned char *) Xmalloc ((unsigned)rbytes)))
+-		_XRead32 (dpy, (long *) *prop, nbytes);
++	    if (rep.nItems < (INT_MAX / sizeof (long))) {
++		nbytes = rep.nItems << 2;
++		rbytes = rep.nItems * sizeof (long) + 1;
++		if ((*prop = Xmalloc (rbytes)))
++		    _XRead32 (dpy, (long *) *prop, nbytes);
++		else
++		    ret = BadAlloc;
++	    }
+ 	    break;
+ 
+ 	default:
+@@ -112,16 +127,13 @@ XGetDeviceProperty(Display* dpy, XDevice* dev,
+ 	     * This part of the code should never be reached.  If it is,
+ 	     * the server sent back a property with an invalid format.
+ 	     */
+-	    _XEatDataWords(dpy, rep.length);
+-	    UnlockDisplay(dpy);
+-	    SyncHandle();
+-	    return(BadImplementation);
++	    ret = BadImplementation;
+ 	}
+ 	if (! *prop) {
+ 	    _XEatDataWords(dpy, rep.length);
+-	    UnlockDisplay(dpy);
+-	    SyncHandle();
+-	    return(BadAlloc);
++	    if (ret == Success)
++		ret = BadAlloc;
++	    goto out;
+ 	}
+ 	(*prop)[rbytes - 1] = '\0';
+     }
+@@ -130,9 +142,10 @@ XGetDeviceProperty(Display* dpy, XDevice* dev,
+     *actual_format = rep.format;
+     *nitems = rep.nItems;
+     *bytes_after = rep.bytesAfter;
++  out:
+     UnlockDisplay (dpy);
+     SyncHandle ();
+ 
+-    return Success;
++    return ret;
+ }
+ 
+-- 
+1.7.9.2
+
+From 03f9746651d8d67c6d449737bd1681eb394b094c Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sun, 10 Mar 2013 00:22:14 -0800
+Subject: [PATCH:libXi 12/13] Avoid integer overflow in XListInputDevices()
+ [CVE-2013-1984 8/8]
+
+If the length of the reply as reported by the Xserver is too long, it
+could overflow the calculation for the size of the buffer to copy the
+reply into, causing memory corruption.
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XListDev.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/XListDev.c b/src/XListDev.c
+index 1fa4747..1c14b96 100644
+--- a/src/XListDev.c
++++ b/src/XListDev.c
+@@ -60,6 +60,7 @@ SOFTWARE.
+ #include <X11/extensions/XInput.h>
+ #include <X11/extensions/extutil.h>
+ #include "XIint.h"
++#include <limits.h>
+ 
+ /* Calculate length field to a multiples of sizeof(XID). XIDs are typedefs
+  * to ulong and thus may be 8 bytes on some platforms. This can trigger a
+@@ -179,7 +180,7 @@ XListInputDevices(
+     XAnyClassPtr Any;
+     char *nptr, *Nptr;
+     int i;
+-    long rlen;
++    unsigned long rlen;
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+ 
+     LockDisplay(dpy);
+@@ -198,9 +199,10 @@ XListInputDevices(
+ 
+     if ((*ndevices = rep.ndevices)) {	/* at least 1 input device */
+ 	size = *ndevices * sizeof(XDeviceInfo);
+-	rlen = rep.length << 2;	/* multiply length by 4    */
+-	list = (xDeviceInfo *) Xmalloc(rlen);
+-	slist = list;
++	if (rep.length < (INT_MAX >> 2)) {
++	    rlen = rep.length << 2;	/* multiply length by 4    */
++	    slist = list = Xmalloc(rlen);
++	}
+ 	if (!slist) {
+ 	    _XEatDataWords(dpy, rep.length);
+ 	    UnlockDisplay(dpy);
+-- 
+1.7.9.2
+
+From 5019f7a8f06b6826cd197d8def6feb841f1490ec Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sun, 10 Mar 2013 00:16:22 -0800
+Subject: [PATCH:libXi 13/13] sign extension issue in XListInputDevices()
+ [CVE-2013-1995]
+
+nptr is (signed) char, which can be negative, and will sign extend
+when added to the int size, which means size can be subtracted from,
+leading to allocating too small a buffer to hold the data being copied
+from the X server's reply.
+
+v2: check that string size fits inside the data read from the server,
+    so that we don't read out of bounds either
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Peter Hutterer <[email protected]>
+---
+ src/XListDev.c |   16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/src/XListDev.c b/src/XListDev.c
+index 1c14b96..b85ff3c 100644
+--- a/src/XListDev.c
++++ b/src/XListDev.c
+@@ -73,7 +73,7 @@ static int pad_to_xid(int base_size)
+     return ((base_size + padsize - 1)/padsize) * padsize;
+ }
+ 
+-static int
++static size_t
+ SizeClassInfo(xAnyClassPtr *any, int num_classes)
+ {
+     int size = 0;
+@@ -170,7 +170,7 @@ XListInputDevices(
+     register Display	*dpy,
+     int			*ndevices)
+ {
+-    int size;
++    size_t size;
+     xListInputDevicesReq *req;
+     xListInputDevicesReply rep;
+     xDeviceInfo *list, *slist = NULL;
+@@ -178,7 +178,7 @@ XListInputDevices(
+     XDeviceInfo *clist = NULL;
+     xAnyClassPtr any, sav_any;
+     XAnyClassPtr Any;
+-    char *nptr, *Nptr;
++    unsigned char *nptr, *Nptr;
+     int i;
+     unsigned long rlen;
+     XExtDisplayInfo *info = XInput_find_display(dpy);
+@@ -217,9 +217,12 @@ XListInputDevices(
+             size += SizeClassInfo(&any, (int)list->num_classes);
+ 	}
+ 
+-	for (i = 0, nptr = (char *)any; i < *ndevices; i++) {
++	Nptr = ((unsigned char *)list) + rlen + 1;
++	for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) {
+ 	    size += *nptr + 1;
+ 	    nptr += (*nptr + 1);
++	    if (nptr > Nptr)
++		goto out;
+ 	}
+ 
+ 	clist = (XDeviceInfoPtr) Xmalloc(size);
+@@ -245,8 +248,8 @@ XListInputDevices(
+ 	}
+ 
+ 	clist = sclist;
+-	nptr = (char *)any;
+-	Nptr = (char *)Any;
++	nptr = (unsigned char *)any;
++	Nptr = (unsigned char *)Any;
+ 	for (i = 0; i < *ndevices; i++, clist++) {
+ 	    clist->name = (char *)Nptr;
+ 	    memcpy(Nptr, nptr + 1, *nptr);
+@@ -256,6 +259,7 @@ XListInputDevices(
+ 	}
+     }
+ 
++  out:
+     XFree((char *)slist);
+     UnlockDisplay(dpy);
+     SyncHandle();
+-- 
+1.7.9.2
+