From 04adcbb8d0e9999441ed2b2167b3dda47a0372c4 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 24 May 2013 09:00:19 +0000 Subject: main/libxi: fix CVE-2013-1984,CVE-2013-1995,CVE-2013-1998 ref #1931 --- main/libxi/APKBUILD | 30 +- ...CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch | 894 +++++++++++++++++++++ 2 files changed, 917 insertions(+), 7 deletions(-) create mode 100644 main/libxi/CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch (limited to 'main/libxi') diff --git a/main/libxi/APKBUILD b/main/libxi/APKBUILD index 9522fe19c..350ef8b25 100644 --- a/main/libxi/APKBUILD +++ b/main/libxi/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa pkgname=libxi pkgver=1.7.1 -pkgrel=0 +pkgrel=1 pkgdesc="X11 Input extension library" url="http://xorg.freedesktop.org" arch="all" @@ -14,23 +14,39 @@ makedepends=" pkgconfig xextproto xproto + libtool autoconf automake util-macros " -source="http://xorg.freedesktop.org/releases/individual/lib/libXi-$pkgver.tar.bz2" +source="http://xorg.freedesktop.org/releases/individual/lib/libXi-$pkgver.tar.bz2 + CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch" +_builddir="$srcdir"/libXi-$pkgver +prepare() { + cd "$_builddir" + for i in $source; do + case $i in + *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;; + esac + done + libtoolize --force && aclocal && autoheader && autoconf \ + && automake --add-missing +} build () { - cd "$srcdir"/libXi-$pkgver + cd "$_builddir" ./configure --prefix=/usr --sysconfdir=/etc || return 1 make || return 1 } package() { - cd "$srcdir"/libXi-$pkgver + cd "$_builddir" make DESTDIR="$pkgdir" install || return 1 rm "$pkgdir"/usr/lib/*.la || return 1 install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING } -md5sums="24d71afed1b86c60d4eb361628d7f47b libXi-1.7.1.tar.bz2" -sha256sums="e92adb6b69c53c51e05c1e65db97e23751b935a693000fb0606c11b88c0066c5 libXi-1.7.1.tar.bz2" -sha512sums="f897bb9ca0bc98b4e5ad7ff770bbafabdc7880122ec50ecbafbcc0e0d4b299cf792484bed6cf87608b652baedd3928341b1bdf110d240a02ac1ac930bab05927 libXi-1.7.1.tar.bz2" +md5sums="24d71afed1b86c60d4eb361628d7f47b libXi-1.7.1.tar.bz2 +75c05fe817230d99194a7593a4f1f8ae CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch" +sha256sums="e92adb6b69c53c51e05c1e65db97e23751b935a693000fb0606c11b88c0066c5 libXi-1.7.1.tar.bz2 +5cc75b20c524ccaf49a0283e16b00a81019c25753eb1a16ae8880e6bc0688e60 CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch" +sha512sums="f897bb9ca0bc98b4e5ad7ff770bbafabdc7880122ec50ecbafbcc0e0d4b299cf792484bed6cf87608b652baedd3928341b1bdf110d240a02ac1ac930bab05927 libXi-1.7.1.tar.bz2 +cf5486fe1daa93190f9fe66ff372bfa3b18a00d0ffff07f222ab1d89f30df786a99959d110c41ae8460257e2f5f4805e861cb8a2858836a6f7413303507bfa70 CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch" diff --git a/main/libxi/CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch b/main/libxi/CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch new file mode 100644 index 000000000..d1209b7fc --- /dev/null +++ b/main/libxi/CVE-2013-1984_CVE-2013-1995_CVE-2013-1998.patch @@ -0,0 +1,894 @@ +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/XExtInt.c b/src/XExtInt.c +index 507573b..d3c6b7c 100644 +--- a/src/XExtInt.c ++++ b/src/XExtInt.c +@@ -1521,6 +1521,7 @@ wireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie) + out = next_block(&ptr_lib, sizeof(XIDeviceEvent)); + out->display = cookie->display; + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->extension = in->extension; + out->evtype = in->evtype; + out->send_event = ((in->type & 0x80) != 0); +@@ -1793,6 +1794,7 @@ wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie) + cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len); + + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->display = cookie->display; + out->extension = in->extension; + out->evtype = in->evtype; +@@ -1825,6 +1827,7 @@ wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie) + out->info = (XIHierarchyInfo*)&out[1]; + out->display = cookie->display; + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->extension = in->extension; + out->evtype = in->evtype; + out->send_event = ((in->type & 0x80) != 0); +@@ -1865,6 +1868,7 @@ wireToRawEvent(XExtDisplayInfo *info, xXIRawEvent *in, XGenericEventCookie *cook + + out = next_block(&ptr, sizeof(XIRawEvent)); + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->display = cookie->display; + out->extension = in->extension; + out->evtype = in->evtype; +@@ -1915,6 +1919,7 @@ wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie) + out->buttons.mask = (unsigned char*)&out[1]; + + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->display = cookie->display; + out->extension = in->extension; + out->evtype = in->evtype; +@@ -1957,6 +1962,7 @@ wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie) + cookie->data = out; + + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->extension = in->extension; + out->evtype = in->evtype; + out->send_event = ((in->type & 0x80) != 0); +@@ -1977,6 +1983,7 @@ wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in, + cookie->data = out; + + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->display = cookie->display; + out->extension = in->extension; + out->evtype = in->evtype; +@@ -2004,6 +2011,7 @@ wireToBarrierEvent(xXIBarrierEvent *in, XGenericEventCookie *cookie) + + out->display = cookie->display; + out->type = in->type; ++ out->serial = in->sequenceNumber; + out->extension = in->extension; + out->evtype = in->evtype; + out->send_event = ((in->type & 0x80) != 0); +diff --git a/src/XGMotion.c b/src/XGMotion.c +index 99b1c44..a4c75b6 100644 +--- a/src/XGMotion.c ++++ b/src/XGMotion.c +@@ -59,6 +59,7 @@ SOFTWARE. + #include + #include + #include "XIint.h" ++#include + + 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,15 +105,26 @@ 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); + *nEvents = 0; +- _XEatData(dpy, (unsigned long)size); ++ _XEatDataWords(dpy, rep.length); + UnlockDisplay(dpy); + SyncHandle(); + return (NULL); +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 + #include + #include "XIint.h" ++#include + + #ifdef MIN /* some systems define this in */ + #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); +diff --git a/src/XGetDCtl.c b/src/XGetDCtl.c +index c66212d..51ed0ae 100644 +--- a/src/XGetDCtl.c ++++ b/src/XGetDCtl.c +@@ -61,6 +61,7 @@ SOFTWARE. + #include + #include + #include "XIint.h" ++#include + + 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,10 +91,14 @@ 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) { +- _XEatData(dpy, (unsigned long)nbytes); ++ _XEatDataWords(dpy, rep.length); + goto out; + } + sav = d; +@@ -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; +diff --git a/src/XGetDProp.c b/src/XGetDProp.c +index 5d44f91..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 + #include + #include "XIint.h" ++#include + + 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,17 +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. + */ +- nbytes = rep.length << 2; +- _XEatData(dpy, (unsigned long) nbytes); +- UnlockDisplay(dpy); +- SyncHandle(); +- return(BadImplementation); ++ ret = BadImplementation; + } + if (! *prop) { +- _XEatData(dpy, (unsigned long) nbytes); +- UnlockDisplay(dpy); +- SyncHandle(); +- return(BadAlloc); ++ _XEatDataWords(dpy, rep.length); ++ if (ret == Success) ++ ret = BadAlloc; ++ goto out; + } + (*prop)[rbytes - 1] = '\0'; + } +@@ -131,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; + } + +diff --git a/src/XGetFCtl.c b/src/XGetFCtl.c +index 43afa00..bb50bf3 100644 +--- a/src/XGetFCtl.c ++++ b/src/XGetFCtl.c +@@ -61,6 +61,7 @@ SOFTWARE. + #include + #include + #include "XIint.h" ++#include + + 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,17 +90,28 @@ 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) { +- _XEatData(dpy, (unsigned long)nbytes); ++ _XEatDataWords(dpy, rep.length); + goto out; + } + sav = f; + _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; + +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..b49328c 100644 +--- a/src/XGetProp.c ++++ b/src/XGetProp.c +@@ -60,6 +60,7 @@ SOFTWARE. + #include + #include + #include "XIint.h" ++#include + + XEventClass * + XGetDeviceDontPropagateList( +@@ -68,7 +69,6 @@ XGetDeviceDontPropagateList( + int *count) + { + XEventClass *list = NULL; +- int rlen; + xGetDeviceDontPropagateListReq *req; + xGetDeviceDontPropagateListReply rep; + XExtDisplayInfo *info = XInput_find_display(dpy); +@@ -89,11 +89,11 @@ XGetDeviceDontPropagateList( + } + *count = rep.count; + +- if (*count) { +- rlen = rep.length << 2; +- 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 +@@ -105,7 +105,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/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; +diff --git a/src/XIProperties.c b/src/XIProperties.c +index 83a7a68..32436d1 100644 +--- a/src/XIProperties.c ++++ b/src/XIProperties.c +@@ -38,6 +38,7 @@ + #include + #include + #include "XIint.h" ++#include + + Atom* + XIListProperties(Display* dpy, int deviceid, int *num_props_return) +@@ -64,7 +65,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; + } + +@@ -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); + +@@ -203,8 +204,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); +@@ -217,12 +217,14 @@ 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)) { +- _XEatData(dpy, nbytes); ++ _XEatDataWords(dpy, rep.length); + UnlockDisplay(dpy); + SyncHandle(); + return(BadAlloc); +diff --git a/src/XISelEv.c b/src/XISelEv.c +index fa7eb54..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 + #include + #include "XIint.h" ++#include + + 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,21 +131,38 @@ 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); + +- /* 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); + + 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++; + } + +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 /* for LONG64 on 64-bit platforms */ ++#include ++ ++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..b85ff3c 100644 +--- a/src/XListDev.c ++++ b/src/XListDev.c +@@ -60,6 +60,7 @@ SOFTWARE. + #include + #include + #include "XIint.h" ++#include + + /* 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 +@@ -72,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; +@@ -169,7 +170,7 @@ XListInputDevices( + register Display *dpy, + int *ndevices) + { +- int size; ++ size_t size; + xListInputDevicesReq *req; + xListInputDevicesReply rep; + xDeviceInfo *list, *slist = NULL; +@@ -177,9 +178,9 @@ XListInputDevices( + XDeviceInfo *clist = NULL; + xAnyClassPtr any, sav_any; + XAnyClassPtr Any; +- char *nptr, *Nptr; ++ unsigned char *nptr, *Nptr; + int i; +- long rlen; ++ unsigned long rlen; + XExtDisplayInfo *info = XInput_find_display(dpy); + + LockDisplay(dpy); +@@ -198,11 +199,12 @@ 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) { +- _XEatData(dpy, (unsigned long)rlen); ++ _XEatDataWords(dpy, rep.length); + UnlockDisplay(dpy); + SyncHandle(); + return (XDeviceInfo *) NULL; +@@ -215,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); +@@ -243,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); +@@ -254,6 +259,7 @@ XListInputDevices( + } + } + ++ out: + XFree((char *)slist); + UnlockDisplay(dpy); + SyncHandle(); +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..3836777 100644 +--- a/src/XQueryDv.c ++++ b/src/XQueryDv.c +@@ -59,6 +59,7 @@ SOFTWARE. + #include + #include + #include "XIint.h" ++#include + + 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,16 +88,22 @@ 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) { +- _XEatData(dpy, (unsigned long)rlen); ++ _XEatDataWords(dpy, rep.length); + goto out; + } + _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); -- cgit v1.2.3