diff options
author | Tobias Stoeckmann <tobias@stoeckmann.org> | 2016-09-25 22:31:34 +0200 |
---|---|---|
committer | Matthieu Herrb <matthieu@herrb.eu> | 2016-09-25 22:31:34 +0200 |
commit | 19a9cd607de73947fcfb104682f203ffe4e1f4e5 (patch) | |
tree | 5fbb89ac3f543a3b25d9eb9e85def0e19b174e9e /src/XIQueryDevice.c | |
parent | 2286282f965064176b3b1492646c6e2e0f4ab7dd (diff) |
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 <tobias@stoeckmann.org>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
Diffstat (limited to 'src/XIQueryDevice.c')
-rw-r--r-- | src/XIQueryDevice.c | 36 |
1 files changed, 34 insertions, 2 deletions
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: |