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);