--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/lib/libX11/CVE-2013-1981.patch Wed May 15 13:44:02 2013 -0700
@@ -0,0 +1,1442 @@
+From 4ccc31a3b1decfdec554db5204cd138d32566ed3 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Mar 2013 13:03:55 -0800
+Subject: [PATCH:libX11 01/38] Move repeated #ifdef magic to find PATH_MAX
+ into a common header
+
+Lets stop duplicating the mess all over
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/GetDflt.c | 25 +--------------
+ src/Makefile.am | 1 +
+ src/pathmax.h | 82 +++++++++++++++++++++++++++++++++++++++++++++++++
+ src/xlibi18n/lcFile.c | 24 +--------------
+ 4 files changed, 85 insertions(+), 47 deletions(-)
+ create mode 100644 src/pathmax.h
+
+diff --git a/src/GetDflt.c b/src/GetDflt.c
+index 6f62cd8..4962530 100644
+--- a/src/GetDflt.c
++++ b/src/GetDflt.c
+@@ -52,30 +52,7 @@ SOFTWARE.
+ #include "Xlibint.h"
+ #include <X11/Xos.h>
+ #include <X11/Xresource.h>
+-
+-#ifndef X_NOT_POSIX
+-#ifdef _POSIX_SOURCE
+-#include <limits.h>
+-#else
+-#define _POSIX_SOURCE
+-#include <limits.h>
+-#undef _POSIX_SOURCE
+-#endif
+-#endif
+-#ifndef PATH_MAX
+-#ifdef WIN32
+-#define PATH_MAX 512
+-#else
+-#include <sys/param.h>
+-#endif
+-#ifndef PATH_MAX
+-#ifdef MAXPATHLEN
+-#define PATH_MAX MAXPATHLEN
+-#else
+-#define PATH_MAX 1024
+-#endif
+-#endif
+-#endif
++#include "pathmax.h"
+
+ #ifdef XTHREADS
+ #include <X11/Xthreads.h>
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 71e02e7..27b74b0 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -210,6 +210,7 @@ libX11_la_SOURCES = \
+ ParseCmd.c \
+ ParseCol.c \
+ ParseGeom.c \
++ pathmax.h \
+ PeekEvent.c \
+ PeekIfEv.c \
+ Pending.c \
+diff --git a/src/pathmax.h b/src/pathmax.h
+new file mode 100644
+index 0000000..a8aaaa5
+--- /dev/null
++++ b/src/pathmax.h
+@@ -0,0 +1,82 @@
++
++/***********************************************************
++
++Copyright 1987, 1988, 1998 The Open Group
++
++Permission to use, copy, modify, distribute, and sell this software and its
++documentation for any purpose is hereby granted without fee, provided that
++the above copyright notice appear in all copies and that both that
++copyright notice and this permission notice appear in supporting
++documentation.
++
++The above copyright notice and this permission notice shall be included in
++all copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
++AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++
++Except as contained in this notice, the name of The Open Group shall not be
++used in advertising or otherwise to promote the sale, use or other dealings
++in this Software without prior written authorization from The Open Group.
++
++
++Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
++
++ All Rights Reserved
++
++Permission to use, copy, modify, and distribute this software and its
++documentation for any purpose and without fee is hereby granted,
++provided that the above copyright notice appear in all copies and that
++both that copyright notice and this permission notice appear in
++supporting documentation, and that the name of Digital not be
++used in advertising or publicity pertaining to distribution of the
++software without specific, written prior permission.
++
++DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
++ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
++DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
++ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
++WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
++ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
++SOFTWARE.
++
++******************************************************************/
++
++/*
++ * Provides a single definition of PATH_MAX instead of replicating this mess
++ * in multiple files
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++#include <X11/Xos.h>
++
++#ifndef X_NOT_POSIX
++#ifdef _POSIX_SOURCE
++#include <limits.h>
++#else
++#define _POSIX_SOURCE
++#include <limits.h>
++#undef _POSIX_SOURCE
++#endif
++#endif
++#ifndef PATH_MAX
++#ifdef WIN32
++#define PATH_MAX 512
++#else
++#include <sys/param.h>
++#endif
++#ifndef PATH_MAX
++#ifdef MAXPATHLEN
++#define PATH_MAX MAXPATHLEN
++#else
++#define PATH_MAX 1024
++#endif
++#endif
++#endif
++
+diff --git a/src/xlibi18n/lcFile.c b/src/xlibi18n/lcFile.c
+index 2c06fa2..61a14e7 100644
+--- a/src/xlibi18n/lcFile.c
++++ b/src/xlibi18n/lcFile.c
+@@ -54,29 +54,7 @@
+
+ #define XLC_BUFSIZE 256
+
+-#ifndef X_NOT_POSIX
+-#ifdef _POSIX_SOURCE
+-#include <limits.h>
+-#else
+-#define _POSIX_SOURCE
+-#include <limits.h>
+-#undef _POSIX_SOURCE
+-#endif
+-#endif
+-#ifndef PATH_MAX
+-#ifdef WIN32
+-#define PATH_MAX 512
+-#else
+-#include <sys/param.h>
+-#endif
+-#ifndef PATH_MAX
+-#ifdef MAXPATHLEN
+-#define PATH_MAX MAXPATHLEN
+-#else
+-#define PATH_MAX 1024
+-#endif
+-#endif
+-#endif
++#include "pathmax.h"
+
+ #define NUM_LOCALEDIR 64
+
+--
+1.7.9.2
+
+From bee46fae41c84f42cb025811ec767c9c8cfcb32c Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 21:05:27 -0800
+Subject: [PATCH:libX11 03/38] integer overflow in _XQueryFont() on 32-bit
+ platforms [CVE-2013-1981 1/13]
+
+If the CARD32 reply.nCharInfos * sizeof(XCharStruct) overflows an
+unsigned long, then too small of a buffer will be allocated for the
+data copied in from the reply.
+
+v2: Fix reply_left calculations, check calculated sizes fit in reply_left
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+---
+ src/Font.c | 35 +++++++++++++++++++++++------------
+ 1 file changed, 23 insertions(+), 12 deletions(-)
+
+diff --git a/src/Font.c b/src/Font.c
+index 25e1790..9ee127c 100644
+--- a/src/Font.c
++++ b/src/Font.c
+@@ -31,6 +31,7 @@ authorization from the X Consortium and the XFree86 Project.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
+
+ #if defined(XF86BIGFONT)
+ #define USE_XF86BIGFONT
+@@ -183,7 +184,8 @@ _XQueryFont (
+ unsigned long seq)
+ {
+ register XFontStruct *fs;
+- register long nbytes;
++ unsigned long nbytes;
++ unsigned long reply_left; /* unused data words left in reply buffer */
+ xQueryFontReply reply;
+ register xResourceReq *req;
+ register _XExtension *ext;
+@@ -211,9 +213,10 @@ _XQueryFont (
+ }
+ if (seq)
+ DeqAsyncHandler(dpy, &async);
++ reply_left = reply.length -
++ ((SIZEOF(xQueryFontReply) - SIZEOF(xReply)) >> 2);
+ if (! (fs = (XFontStruct *) Xmalloc (sizeof (XFontStruct)))) {
+- _XEatData(dpy, (unsigned long)(reply.nFontProps * SIZEOF(xFontProp) +
+- reply.nCharInfos * SIZEOF(xCharInfo)));
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+ fs->ext_data = NULL;
+@@ -239,16 +242,19 @@ _XQueryFont (
+ */
+ fs->properties = NULL;
+ if (fs->n_properties > 0) {
+- nbytes = reply.nFontProps * sizeof(XFontProp);
+- fs->properties = (XFontProp *) Xmalloc ((unsigned) nbytes);
++ /* nFontProps is a CARD16 */
+ nbytes = reply.nFontProps * SIZEOF(xFontProp);
++ if ((nbytes >> 2) <= reply_left) {
++ size_t pbytes = reply.nFontProps * sizeof(XFontProp);
++ fs->properties = Xmalloc (pbytes);
++ }
+ if (! fs->properties) {
+ Xfree((char *) fs);
+- _XEatData(dpy, (unsigned long)
+- (nbytes + reply.nCharInfos * SIZEOF(xCharInfo)));
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+ _XRead32 (dpy, (long *)fs->properties, nbytes);
++ reply_left -= (nbytes >> 2);
+ }
+ /*
+ * If no characters in font, then it is a bad font, but
+@@ -256,16 +262,21 @@ _XQueryFont (
+ */
+ fs->per_char = NULL;
+ if (reply.nCharInfos > 0){
+- nbytes = reply.nCharInfos * sizeof(XCharStruct);
+- if (! (fs->per_char = (XCharStruct *) Xmalloc ((unsigned) nbytes))) {
++ /* nCharInfos is a CARD32 */
++ if (reply.nCharInfos < (INT_MAX / sizeof(XCharStruct))) {
++ nbytes = reply.nCharInfos * SIZEOF(xCharInfo);
++ if ((nbytes >> 2) <= reply_left) {
++ size_t cibytes = reply.nCharInfos * sizeof(XCharStruct);
++ fs->per_char = Xmalloc (cibytes);
++ }
++ }
++ if (! fs->per_char) {
+ if (fs->properties) Xfree((char *) fs->properties);
+ Xfree((char *) fs);
+- _XEatData(dpy, (unsigned long)
+- (reply.nCharInfos * SIZEOF(xCharInfo)));
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+
+- nbytes = reply.nCharInfos * SIZEOF(xCharInfo);
+ _XRead16 (dpy, (char *)fs->per_char, nbytes);
+ }
+
+--
+1.7.9.2
+
+From ed74729326d04eb736dd2cdffa394c9638a28ab2 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 21:05:27 -0800
+Subject: [PATCH:libX11 04/38] integer overflow in _XF86BigfontQueryFont()
+ [CVE-2013-1981 2/13]
+
+Similar to _XQueryFont, but with more ways to go wrong and overflow.
+Only compiled if libX11 is built with XF86BigFont support.
+
+v2: Fix reply_left calculations, check calculated sizes fit in reply_left
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+---
+ src/Font.c | 42 +++++++++++++++++++++++++-----------------
+ 1 file changed, 25 insertions(+), 17 deletions(-)
+
+diff --git a/src/Font.c b/src/Font.c
+index 9ee127c..5dbdb29 100644
+--- a/src/Font.c
++++ b/src/Font.c
+@@ -403,7 +403,8 @@ _XF86BigfontQueryFont (
+ unsigned long seq)
+ {
+ register XFontStruct *fs;
+- register long nbytes;
++ unsigned long nbytes;
++ unsigned long reply_left; /* unused data left in reply buffer */
+ xXF86BigfontQueryFontReply reply;
+ register xXF86BigfontQueryFontReq *req;
+ register _XExtension *ext;
+@@ -456,13 +457,10 @@ _XF86BigfontQueryFont (
+ DeqAsyncHandler(dpy, &async2);
+ if (seq)
+ DeqAsyncHandler(dpy, &async1);
++ reply_left = reply.length -
++ ((SIZEOF(xXF86BigfontQueryFontReply) - SIZEOF(xReply)) >> 2);
+ if (! (fs = (XFontStruct *) Xmalloc (sizeof (XFontStruct)))) {
+- _XEatData(dpy,
+- reply.nFontProps * SIZEOF(xFontProp)
+- + (reply.nCharInfos > 0 && reply.shmid == (CARD32)(-1)
+- ? reply.nUniqCharInfos * SIZEOF(xCharInfo)
+- + (reply.nCharInfos+1)/2 * 2 * sizeof(CARD16)
+- : 0));
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+ fs->ext_data = NULL;
+@@ -488,23 +486,32 @@ _XF86BigfontQueryFont (
+ */
+ fs->properties = NULL;
+ if (fs->n_properties > 0) {
+- nbytes = reply.nFontProps * sizeof(XFontProp);
+- fs->properties = (XFontProp *) Xmalloc ((unsigned) nbytes);
++ /* nFontProps is a CARD16 */
+ nbytes = reply.nFontProps * SIZEOF(xFontProp);
++ if ((nbytes >> 2) <= reply_left) {
++ size_t pbytes = reply.nFontProps * sizeof(XFontProp);
++ fs->properties = Xmalloc (pbytes);
++ }
+ if (! fs->properties) {
+ Xfree((char *) fs);
+- _XEatData(dpy,
+- nbytes
+- + (reply.nCharInfos > 0 && reply.shmid == (CARD32)(-1)
+- ? reply.nUniqCharInfos * SIZEOF(xCharInfo)
+- + (reply.nCharInfos+1)/2 * 2 * sizeof(CARD16)
+- : 0));
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+ _XRead32 (dpy, (long *)fs->properties, nbytes);
++ reply_left -= (nbytes >> 2);
+ }
+
+ fs->per_char = NULL;
++#ifndef LONG64
++ /* compares each part to half the maximum, which should be far more than
++ any real font needs, so the combined total doesn't overflow either */
++ if (reply.nUniqCharInfos > ((ULONG_MAX / 2) / SIZEOF(xCharInfo)) ||
++ reply.nCharInfos > ((ULONG_MAX / 2) / sizeof(CARD16))) {
++ Xfree((char *) fs);
++ _XEatDataWords(dpy, reply_left);
++ return (XFontStruct *)NULL;
++ }
++#endif
+ if (reply.nCharInfos > 0) {
+ /* fprintf(stderr, "received font metrics, nCharInfos = %d, nUniqCharInfos = %d, shmid = %d\n", reply.nCharInfos, reply.nUniqCharInfos, reply.shmid); */
+ if (reply.shmid == (CARD32)(-1)) {
+@@ -518,14 +525,14 @@ _XF86BigfontQueryFont (
+ if (!pUniqCI) {
+ if (fs->properties) Xfree((char *) fs->properties);
+ Xfree((char *) fs);
+- _XEatData(dpy, nbytes);
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+ if (! (fs->per_char = (XCharStruct *) Xmalloc (reply.nCharInfos * sizeof(XCharStruct)))) {
+ Xfree((char *) pUniqCI);
+ if (fs->properties) Xfree((char *) fs->properties);
+ Xfree((char *) fs);
+- _XEatData(dpy, nbytes);
++ _XEatDataWords(dpy, reply_left);
+ return (XFontStruct *)NULL;
+ }
+ _XRead16 (dpy, (char *) pUniqCI, nbytes);
+@@ -580,6 +587,7 @@ _XF86BigfontQueryFont (
+ if (!(extcodes->serverCapabilities & CAP_VerifiedLocal)) {
+ struct shmid_ds buf;
+ if (!(shmctl(reply.shmid, IPC_STAT, &buf) >= 0
++ && reply.nCharInfos < (LONG_MAX / sizeof(XCharStruct))
+ && buf.shm_segsz >= reply.shmsegoffset + reply.nCharInfos * sizeof(XCharStruct) + sizeof(CARD32)
+ && *(CARD32 *)(addr + reply.shmsegoffset + reply.nCharInfos * sizeof(XCharStruct)) == extcodes->serverSignature)) {
+ shmdt(addr);
+--
+1.7.9.2
+
+From ce805b2d94edf8109ed8b7f53d440b012b350326 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 22:49:01 -0800
+Subject: [PATCH:libX11 05/38] integer overflow in XListFontsWithInfo()
+ [CVE-2013-1981 3/13]
+
+If the reported number of remaining fonts is too large, the calculations
+to allocate memory for them may overflow, leaving us writing beyond the
+bounds of the allocation.
+
+v2: Fix reply_left calculations, check calculated sizes fit in reply_left
+v3: On error cases, also set values to be returned in pointer args to 0/NULL
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+---
+ src/FontInfo.c | 105 ++++++++++++++++++++++++++------------------------------
+ 1 file changed, 49 insertions(+), 56 deletions(-)
+
+diff --git a/src/FontInfo.c b/src/FontInfo.c
+index fb296b8..4b295a5 100644
+--- a/src/FontInfo.c
++++ b/src/FontInfo.c
+@@ -28,6 +28,7 @@ in this Software without prior written authorization from The Open Group.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
+
+ #if defined(XF86BIGFONT)
+ #define USE_XF86BIGFONT
+@@ -45,10 +46,11 @@ int maxNames,
+ int *actualCount, /* RETURN */
+ XFontStruct **info) /* RETURN */
+ {
+- register long nbytes;
++ unsigned long nbytes;
++ unsigned long reply_left; /* unused data left in reply buffer */
+ register int i;
+ register XFontStruct *fs;
+- register int size = 0;
++ unsigned int size = 0;
+ XFontStruct *finfo = NULL;
+ char **flist = NULL;
+ xListFontsWithInfoReply reply;
+@@ -67,52 +69,44 @@ XFontStruct **info) /* RETURN */
+ if (!_XReply (dpy, (xReply *) &reply,
+ ((SIZEOF(xListFontsWithInfoReply) -
+ SIZEOF(xGenericReply)) >> 2), xFalse)) {
+- for (j=(i-1); (j >= 0); j--) {
+- Xfree(flist[j]);
+- if (finfo[j].properties) Xfree((char *) finfo[j].properties);
+- }
+- if (flist) Xfree((char *) flist);
+- if (finfo) Xfree((char *) finfo);
+- UnlockDisplay(dpy);
+- SyncHandle();
+- return ((char **) NULL);
++ reply.nameLength = 0; /* avoid trying to read more replies */
++ reply_left = 0;
++ goto badmem;
+ }
+- if (reply.nameLength == 0)
++ reply_left = reply.length -
++ ((SIZEOF(xListFontsWithInfoReply) - SIZEOF(xGenericReply)) >> 2);
++ if (reply.nameLength == 0) {
++ _XEatDataWords(dpy, reply_left);
+ break;
++ }
++ if (reply.nReplies >= (INT_MAX - i)) /* avoid overflowing size */
++ goto badmem;
+ if ((i + reply.nReplies) >= size) {
+ size = i + reply.nReplies + 1;
+
++ if (size >= (INT_MAX / sizeof(XFontStruct)))
++ goto badmem;
++
+ if (finfo) {
+- XFontStruct * tmp_finfo = (XFontStruct *)
+- Xrealloc ((char *) finfo,
+- (unsigned) (sizeof(XFontStruct) * size));
+- char ** tmp_flist = (char **)
+- Xrealloc ((char *) flist,
+- (unsigned) (sizeof(char *) * (size+1)));
++ XFontStruct * tmp_finfo;
++ char ** tmp_flist;
+
++ tmp_finfo = Xrealloc (finfo, sizeof(XFontStruct) * size);
+ if (tmp_finfo)
+ finfo = tmp_finfo;
++ else
++ goto badmem;
++
++ tmp_flist = Xrealloc (flist, sizeof(char *) * (size+1));
+ if (tmp_flist)
+ flist = tmp_flist;
+-
+- if ((! tmp_finfo) || (! tmp_flist)) {
+- /* free all the memory that we allocated */
+- for (j=(i-1); (j >= 0); j--) {
+- Xfree(flist[j]);
+- if (finfo[j].properties)
+- Xfree((char *) finfo[j].properties);
+- }
+- Xfree((char *) flist);
+- Xfree((char *) finfo);
+- goto clearwire;
+- }
++ else
++ goto badmem;
+ }
+ else {
+- if (! (finfo = (XFontStruct *)
+- Xmalloc((unsigned) (sizeof(XFontStruct) * size))))
++ if (! (finfo = Xmalloc(sizeof(XFontStruct) * size)))
+ goto clearwire;
+- if (! (flist = (char **)
+- Xmalloc((unsigned) (sizeof(char *) * (size+1))))) {
++ if (! (flist = Xmalloc(sizeof(char *) * (size+1)))) {
+ Xfree((char *) finfo);
+ goto clearwire;
+ }
+@@ -138,24 +132,27 @@ XFontStruct **info) /* RETURN */
+ fs->max_bounds = * (XCharStruct *) &reply.maxBounds;
+
+ fs->n_properties = reply.nFontProps;
++ fs->properties = NULL;
+ if (fs->n_properties > 0) {
+- nbytes = reply.nFontProps * sizeof(XFontProp);
+- if (! (fs->properties = (XFontProp *) Xmalloc((unsigned) nbytes)))
+- goto badmem;
++ /* nFontProps is a CARD16 */
+ nbytes = reply.nFontProps * SIZEOF(xFontProp);
++ if ((nbytes >> 2) <= reply_left) {
++ size_t pbytes = reply.nFontProps * sizeof(XFontProp);
++ fs->properties = Xmalloc (pbytes);
++ }
++ if (! fs->properties)
++ goto badmem;
+ _XRead32 (dpy, (long *)fs->properties, nbytes);
++ reply_left -= (nbytes >> 2);
++ }
+
+- } else
+- fs->properties = NULL;
+-
+- j = reply.nameLength + 1;
++ /* nameLength is a CARD8 */
++ nbytes = reply.nameLength + 1;
+ if (!i)
+- j++; /* make first string 1 byte longer, to match XListFonts */
+- flist[i] = (char *) Xmalloc ((unsigned int) j);
++ nbytes++; /* make first string 1 byte longer, to match XListFonts */
++ flist[i] = Xmalloc (nbytes);
+ if (! flist[i]) {
+ if (finfo[i].properties) Xfree((char *) finfo[i].properties);
+- nbytes = (reply.nameLength + 3) & ~3;
+- _XEatData(dpy, (unsigned long) nbytes);
+ goto badmem;
+ }
+ if (!i) {
+@@ -185,19 +182,15 @@ XFontStruct **info) /* RETURN */
+
+ clearwire:
+ /* Clear the wire. */
+- do {
+- if (reply.nFontProps)
+- _XEatData(dpy, (unsigned long)
+- (reply.nFontProps * SIZEOF(xFontProp)));
+- nbytes = (reply.nameLength + 3) & ~3;
+- _XEatData(dpy, (unsigned long) nbytes);
+- }
+- while (_XReply(dpy,(xReply *) &reply, ((SIZEOF(xListFontsWithInfoReply) -
+- SIZEOF(xGenericReply)) >> 2),
+- xFalse) && (reply.nameLength != 0));
+-
++ _XEatDataWords(dpy, reply_left);
++ while ((reply.nameLength != 0) &&
++ _XReply(dpy, (xReply *) &reply,
++ ((SIZEOF(xListFontsWithInfoReply) - SIZEOF(xGenericReply))
++ >> 2), xTrue));
+ UnlockDisplay(dpy);
+ SyncHandle();
++ *info = NULL;
++ *actualCount = 0;
+ return (char **) NULL;
+ }
+
+--
+1.7.9.2
+
+From 3eaf200b6d60de2284c6d7e0180ddf9cabf25a64 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 22:49:01 -0800
+Subject: [PATCH:libX11 06/38] integer overflow in XGetMotionEvents()
+ [CVE-2013-1981 4/13]
+
+If the reported number of motion events is too large, the calculations
+to allocate memory for them may overflow, leaving us writing beyond the
+bounds of the allocation.
+
+v2: Ensure nEvents is set to 0 when returning NULL events pointer
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+---
+ src/GetMoEv.c | 26 +++++++++++---------------
+ 1 file changed, 11 insertions(+), 15 deletions(-)
+
+diff --git a/src/GetMoEv.c b/src/GetMoEv.c
+index 3db176f..ad9c772 100644
+--- a/src/GetMoEv.c
++++ b/src/GetMoEv.c
+@@ -28,6 +28,7 @@ in this Software without prior written authorization from The Open Group.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
+
+ XTimeCoord *XGetMotionEvents(
+ register Display *dpy,
+@@ -39,7 +40,6 @@ XTimeCoord *XGetMotionEvents(
+ xGetMotionEventsReply rep;
+ register xGetMotionEventsReq *req;
+ XTimeCoord *tc = NULL;
+- long nbytes;
+ LockDisplay(dpy);
+ GetReq(GetMotionEvents, req);
+ req->window = w;
+@@ -52,26 +52,22 @@ XTimeCoord *XGetMotionEvents(
+ return (NULL);
+ }
+
+- if (rep.nEvents) {
+- if (! (tc = (XTimeCoord *)
+- Xmalloc( (unsigned)
+- (nbytes = (long) rep.nEvents * sizeof(XTimeCoord))))) {
+- _XEatData (dpy, (unsigned long) nbytes);
+- UnlockDisplay(dpy);
+- SyncHandle();
+- return (NULL);
+- }
++ if (rep.nEvents && (rep.nEvents < (INT_MAX / sizeof(XTimeCoord))))
++ tc = Xmalloc(rep.nEvents * sizeof(XTimeCoord));
++ if (tc == NULL) {
++ /* server returned either no events or a bad event count */
++ *nEvents = 0;
++ _XEatDataWords (dpy, rep.length);
+ }
+-
+- *nEvents = rep.nEvents;
+- nbytes = SIZEOF (xTimecoord);
++ else
+ {
+ register XTimeCoord *tcptr;
+- register int i;
++ unsigned int i;
+ xTimecoord xtc;
+
++ *nEvents = (int) rep.nEvents;
+ for (i = rep.nEvents, tcptr = tc; i > 0; i--, tcptr++) {
+- _XRead (dpy, (char *) &xtc, nbytes);
++ _XRead (dpy, (char *) &xtc, SIZEOF (xTimecoord));
+ tcptr->time = xtc.time;
+ tcptr->x = cvtINT16toShort (xtc.x);
+ tcptr->y = cvtINT16toShort (xtc.y);
+--
+1.7.9.2
+
+From b0528a42d6728c119af2fcb28407efa7b0b9fe54 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 22:49:01 -0800
+Subject: [PATCH:libX11 07/38] integer overflow in XListHosts() [CVE-2013-1981
+ 5/13]
+
+If the reported number of host entries is too large, the calculations
+to allocate memory for them may overflow, leaving us writing beyond the
+bounds of the allocation.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/LiHosts.c | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/src/LiHosts.c b/src/LiHosts.c
+index 0f5e837..83cf3c7 100644
+--- a/src/LiHosts.c
++++ b/src/LiHosts.c
+@@ -62,6 +62,8 @@ X Window System is a trademark of The Open Group.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
++
+ /*
+ * can be freed using XFree.
+ */
+@@ -73,7 +75,6 @@ XHostAddress *XListHosts (
+ {
+ register XHostAddress *outbuf = NULL, *op;
+ xListHostsReply reply;
+- long nbytes;
+ unsigned char *buf, *bp;
+ register unsigned i;
+ register xListHostsReq *req;
+@@ -90,19 +91,26 @@ XHostAddress *XListHosts (
+ }
+
+ if (reply.nHosts) {
+- nbytes = reply.length << 2; /* compute number of bytes in reply */
++ unsigned long nbytes = reply.length << 2; /* number of bytes in reply */
++ const unsigned long max_hosts = INT_MAX /
++ (sizeof(XHostAddress) + sizeof(XServerInterpretedAddress));
++
++ if (reply.nHosts < max_hosts) {
++ unsigned long hostbytes = reply.nHosts *
++ (sizeof(XHostAddress) + sizeof(XServerInterpretedAddress));
+
+- op = outbuf = (XHostAddress *)
+- Xmalloc((unsigned) (nbytes +
+- (reply.nHosts * sizeof(XHostAddress)) +
+- (reply.nHosts * sizeof(XServerInterpretedAddress))));
++ if (reply.length < (INT_MAX >> 2) &&
++ (hostbytes >> 2) < ((INT_MAX >> 2) - reply.length))
++ outbuf = Xmalloc(nbytes + hostbytes);
++ }
+
+ if (! outbuf) {
+- _XEatData(dpy, (unsigned long) nbytes);
++ _XEatDataWords(dpy, reply.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return (XHostAddress *) NULL;
+ }
++ op = outbuf;
+ sip = (XServerInterpretedAddress *)
+ (((unsigned char *) outbuf) + (reply.nHosts * sizeof(XHostAddress)));
+ bp = buf = ((unsigned char *) sip)
+--
+1.7.9.2
+
+From fa0ab9b0a1e2dae89895919a9dcdff5f6851ee64 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Mar 2013 11:44:19 -0800
+Subject: [PATCH:libX11 20/38] Integer overflows in stringSectionSize() cause
+ buffer overflow in ReadColornameDB()
+ [CVE-2013-1981 6/13]
+
+LoadColornameDB() calls stringSectionSize() to do a first pass over the
+file (which may be provided by the user via XCMSDB environment variable)
+to determine how much memory needs to be allocated to read in the file,
+then allocates the returned sizes and calls ReadColornameDB() to load the
+data from the file into that newly allocated memory.
+
+If stringSectionSize() overflows the signed ints used to calculate the
+file size (say if you have an xcmsdb with ~4 billion lines in or a
+combined string length of ~4 gig - which while it may have been
+inconceivable when Xlib was written, is quite possible today), then
+LoadColornameDB() may allocate a memory buffer much smaller than the
+amount of data ReadColornameDB() will write to it.
+
+The total size is left limited to an int, because if your xcmsdb file
+is larger than 2gb, you're doing it wrong.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/xcms/cmsColNm.c | 27 +++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/src/xcms/cmsColNm.c b/src/xcms/cmsColNm.c
+index a6749c0..8d0d4a7 100644
+--- a/src/xcms/cmsColNm.c
++++ b/src/xcms/cmsColNm.c
+@@ -40,6 +40,7 @@
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <ctype.h>
++#include <limits.h>
+ #define XK_LATIN1
+ #include <X11/keysymdef.h>
+ #include "Cv.h"
+@@ -542,7 +543,10 @@ stringSectionSize(
+ char *pBuf;
+ char *f1;
+ char *f2;
+- int i;
++ size_t i;
++
++ unsigned int numEntries = 0;
++ unsigned int sectionSize = 0;
+
+ *pNumEntries = 0;
+ *pSectionSize = 0;
+@@ -576,26 +580,37 @@ stringSectionSize(
+ return(XcmsFailure);
+ }
+
+- (*pNumEntries)++;
++ numEntries++;
++ if (numEntries >= INT_MAX)
++ return(XcmsFailure);
+
+- (*pSectionSize) += (i = strlen(f1)) + 1;
++ i = strlen(f1);
++ if (i >= INT_MAX - sectionSize)
++ return(XcmsFailure);
++ sectionSize += i + 1;
+ for (; i; i--, f1++) {
+ /* REMOVE SPACES FROM COUNT */
+ if (isspace(*f1)) {
+- (*pSectionSize)--;
++ sectionSize--;
+ }
+ }
+
+- (*pSectionSize) += (i = strlen(f2)) + 1;
++ i = strlen(f2);
++ if (i >= INT_MAX - sectionSize)
++ return(XcmsFailure);
++ sectionSize += i + 1;
+ for (; i; i--, f2++) {
+ /* REMOVE SPACES FROM COUNT */
+ if (isspace(*f2)) {
+- (*pSectionSize)--;
++ sectionSize--;
+ }
+ }
+
+ }
+
++ *pNumEntries = (int) numEntries;
++ *pSectionSize = (int) sectionSize;
++
+ return(XcmsSuccess);
+ }
+
+--
+1.7.9.2
+
+From de8462f73c41b2253d920a713725c96591ab5690 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 18:37:37 -0800
+Subject: [PATCH:libX11 21/38] integer overflow in ReadInFile() in Xrm.c
+ [CVE-2013-1981 7/13]
+
+Called from XrmGetFileDatabase() which gets called from InitDefaults()
+which gets the filename from getenv ("XENVIRONMENT")
+
+If file is exactly 0xffffffff bytes long (or longer and truncates to
+0xffffffff, on implementations where off_t is larger than an int),
+then size may be set to a value which overflows causing less memory
+to be allocated than is written to by the following read() call.
+
+size is left limited to an int, because if your Xresources file is
+larger than 2gb, you're very definitely doing it wrong.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/Xrm.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/Xrm.c b/src/Xrm.c
+index d6899d9..3e29ab0 100644
+--- a/src/Xrm.c
++++ b/src/Xrm.c
+@@ -62,6 +62,7 @@ from The Open Group.
+ #endif
+ #include <X11/Xos.h>
+ #include <sys/stat.h>
++#include <limits.h>
+ #include "Xresinternal.h"
+ #include "Xresource.h"
+
+@@ -1594,11 +1595,12 @@ ReadInFile(_Xconst char *filename)
+ */
+ {
+ struct stat status_buffer;
+- if ( (fstat(fd, &status_buffer)) == -1 ) {
++ if ( ((fstat(fd, &status_buffer)) == -1 ) ||
++ (status_buffer.st_size >= INT_MAX) ) {
+ close (fd);
+ return (char *)NULL;
+ } else
+- size = status_buffer.st_size;
++ size = (int) status_buffer.st_size;
+ }
+
+ if (!(filebuf = Xmalloc(size + 1))) { /* leave room for '\0' */
+--
+1.7.9.2
+
+From 9a8117101fe3c6c615fbce34eca244f149bb2766 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 1 Mar 2013 18:37:37 -0800
+Subject: [PATCH:libX11 24/38] integer truncation in _XimParseStringFile()
+ [CVE-2013-1981 8/13]
+
+Called from _XimCreateDefaultTree() which uses getenv("XCOMPOSEFILE")
+to specify filename.
+
+If the size of off_t is larger than the size of unsigned long (as in
+32-bit builds with large file flags), a file larger than 4 gigs could
+have its size truncated, leading to data from that file being written
+past the end of the undersized buffer allocated for it.
+
+While configure.ac does not use AC_SYS_LARGEFILE to set large file mode,
+builders may have added the large file compilation flags to CFLAGS on
+their own.
+
+size is left limited to an int, because if your Xim file is
+larger than 2gb, you're doing it wrong.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ modules/im/ximcp/imLcPrs.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/modules/im/ximcp/imLcPrs.c b/modules/im/ximcp/imLcPrs.c
+index 4c7d6f0..bcf4579 100644
+--- a/modules/im/ximcp/imLcPrs.c
++++ b/modules/im/ximcp/imLcPrs.c
+@@ -41,6 +41,7 @@ OR PERFORMANCE OF THIS SOFTWARE.
+ #include "Ximint.h"
+ #include <sys/stat.h>
+ #include <stdio.h>
++#include <limits.h>
+
+ #define XLC_BUFSIZE 256
+
+@@ -688,6 +689,8 @@ parsestringfile(
+
+ if (fstat (fileno (fp), &st) != -1) {
+ unsigned long size = (unsigned long) st.st_size;
++ if (st.st_size >= INT_MAX)
++ return;
+ if (size <= sizeof tb) tbp = tb;
+ else tbp = malloc (size);
+
+--
+1.7.9.2
+
+From 692e43c2d5fbc56f38371f3f44a1d339595f0056 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Mar 2013 13:18:48 -0800
+Subject: [PATCH:libX11 25/38] integer overflows in TransFileName()
+ [CVE-2013-1981 9/13]
+
+When trying to process file paths the tokens %H, %L, & %S are expanded
+to $HOME, the standard compose file path & the xlocaledir path.
+If enough of these tokens are repeated and values like $HOME are set to
+very large values, the calculation of the total string size required to
+hold the expanded path can overflow, resulting in allocating a smaller
+string than the amount of data we'll write to it.
+
+Simply restrict all of these values, and the total path size to PATH_MAX,
+because really, that's all you should need for a filename path.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ modules/im/ximcp/Makefile.am | 1 +
+ modules/im/ximcp/imLcPrs.c | 45 +++++++++++++++++++++++++++++++-----------
+ 2 files changed, 35 insertions(+), 11 deletions(-)
+
+diff --git a/modules/im/ximcp/Makefile.am b/modules/im/ximcp/Makefile.am
+index 16a6ca8..8aae839 100644
+--- a/modules/im/ximcp/Makefile.am
++++ b/modules/im/ximcp/Makefile.am
+@@ -6,6 +6,7 @@ AM_CPPFLAGS= \
+ -I$(top_srcdir)/src/xcms \
+ -I$(top_srcdir)/src/xkb \
+ -I$(top_srcdir)/src/xlibi18n \
++ -I$(top_srcdir)/src \
+ -D_BSD_SOURCE -DXIM_t -DTRANS_CLIENT
+
+ AM_CFLAGS= \
+diff --git a/modules/im/ximcp/imLcPrs.c b/modules/im/ximcp/imLcPrs.c
+index bcf4579..f3627a0 100644
+--- a/modules/im/ximcp/imLcPrs.c
++++ b/modules/im/ximcp/imLcPrs.c
+@@ -42,6 +42,7 @@ OR PERFORMANCE OF THIS SOFTWARE.
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <limits.h>
++#include "pathmax.h"
+
+ #define XLC_BUFSIZE 256
+
+@@ -307,9 +308,9 @@ static char*
+ TransFileName(Xim im, char *name)
+ {
+ char *home = NULL, *lcCompose = NULL;
+- char dir[XLC_BUFSIZE];
+- char *i = name, *ret, *j;
+- int l = 0;
++ char dir[XLC_BUFSIZE] = "";
++ char *i = name, *ret = NULL, *j;
++ size_t l = 0;
+
+ while (*i) {
+ if (*i == '%') {
+@@ -319,30 +320,51 @@ TransFileName(Xim im, char *name)
+ l++;
+ break;
+ case 'H':
+- home = getenv("HOME");
+- if (home)
+- l += strlen(home);
++ if (home == NULL)
++ home = getenv("HOME");
++ if (home) {
++ size_t Hsize = strlen(home);
++ if (Hsize > PATH_MAX)
++ /* your home directory length is ridiculous */
++ goto end;
++ l += Hsize;
++ }
+ break;
+ case 'L':
+ if (lcCompose == NULL)
+ lcCompose = _XlcFileName(im->core.lcd, COMPOSE_FILE);
+- if (lcCompose)
+- l += strlen(lcCompose);
++ if (lcCompose) {
++ size_t Lsize = strlen(lcCompose);
++ if (Lsize > PATH_MAX)
++ /* your compose pathname length is ridiculous */
++ goto end;
++ l += Lsize;
++ }
+ break;
+ case 'S':
+- xlocaledir(dir, XLC_BUFSIZE);
+- l += strlen(dir);
++ if (dir[0] == '\0')
++ xlocaledir(dir, XLC_BUFSIZE);
++ if (dir[0]) {
++ size_t Ssize = strlen(dir);
++ if (Ssize > PATH_MAX)
++ /* your locale directory path length is ridiculous */
++ goto end;
++ l += Ssize;
++ }
+ break;
+ }
+ } else {
+ l++;
+ }
+ i++;
++ if (l > PATH_MAX)
++ /* your expanded path length is ridiculous */
++ goto end;
+ }
+
+ j = ret = Xmalloc(l+1);
+ if (ret == NULL)
+- return ret;
++ goto end;
+ i = name;
+ while (*i) {
+ if (*i == '%') {
+@@ -374,6 +396,7 @@ TransFileName(Xim im, char *name)
+ }
+ }
+ *j = '\0';
++end:
+ Xfree(lcCompose);
+ return ret;
+ }
+--
+1.7.9.2
+
+From ea8bc513f6849cadc93dd68de8a562d6e63b19d5 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Fri, 8 Mar 2013 22:25:35 -0800
+Subject: [PATCH:libX11 26/38] integer overflow in XGetWindowProperty()
+ [CVE-2013-1981 10/13]
+
+If the reported number of properties is too large, the calculations
+to allocate memory for them may overflow, leaving us returning less
+memory to the caller than implied by the value written to *nitems.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/GetProp.c | 25 ++++++++++++++++---------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/src/GetProp.c b/src/GetProp.c
+index 5d6e0b8..ae14edc 100644
+--- a/src/GetProp.c
++++ b/src/GetProp.c
+@@ -28,6 +28,7 @@ in this Software without prior written authorization from The Open Group.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
+
+ int
+ XGetWindowProperty(
+@@ -66,8 +67,17 @@ XGetWindowProperty(
+
+ *prop = (unsigned char *) NULL;
+ if (reply.propertyType != None) {
+- long nbytes, netbytes;
+- switch (reply.format) {
++ unsigned long nbytes, netbytes;
++ int format = reply.format;
++
++ /*
++ * Protect against both integer overflow and just plain oversized
++ * memory allocation - no server should ever return this many props.
++ */
++ if (reply.nItems >= (INT_MAX >> 4))
++ format = -1; /* fall through to default error case */
++
++ switch (format) {
+ /*
+ * One extra byte is malloced than is needed to contain the property
+ * data, but this last byte is null terminated and convenient for
+@@ -76,24 +86,21 @@ XGetWindowProperty(
+ */
+ case 8:
+ nbytes = netbytes = reply.nItems;
+- if (nbytes + 1 > 0 &&
+- (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1)))
++ if (nbytes + 1 > 0 && (*prop = Xmalloc (nbytes + 1)))
+ _XReadPad (dpy, (char *) *prop, netbytes);
+ break;
+
+ case 16:
+ nbytes = reply.nItems * sizeof (short);
+ netbytes = reply.nItems << 1;
+- if (nbytes + 1 > 0 &&
+- (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1)))
++ if (nbytes + 1 > 0 && (*prop = Xmalloc (nbytes + 1)))
+ _XRead16Pad (dpy, (short *) *prop, netbytes);
+ break;
+
+ case 32:
+ nbytes = reply.nItems * sizeof (long);
+ netbytes = reply.nItems << 2;
+- if (nbytes + 1 > 0 &&
+- (*prop = (unsigned char *) Xmalloc ((unsigned)nbytes + 1)))
++ if (nbytes + 1 > 0 && (*prop = Xmalloc (nbytes + 1)))
+ _XRead32 (dpy, (long *) *prop, netbytes);
+ break;
+
+@@ -115,7 +122,7 @@ XGetWindowProperty(
+ break;
+ }
+ if (! *prop) {
+- _XEatData(dpy, (unsigned long) netbytes);
++ _XEatDataWords(dpy, reply.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return(BadAlloc); /* not Success */
+--
+1.7.9.2
+
+From 0febed454ee211deb6ae56d4febf71393e0aff2b Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Mar 2013 15:08:21 -0800
+Subject: [PATCH:libX11 27/38] integer overflow in XGetImage() [CVE-2013-1981
+ 11/13]
+
+Ensure that we don't underallocate when the server claims to have sent a
+very large reply.
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/GetImage.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/src/GetImage.c b/src/GetImage.c
+index e8f1b03..c461abc 100644
+--- a/src/GetImage.c
++++ b/src/GetImage.c
+@@ -30,6 +30,7 @@ in this Software without prior written authorization from The Open Group.
+ #include "Xlibint.h"
+ #include <X11/Xutil.h> /* for XDestroyImage */
+ #include "ImUtil.h"
++#include <limits.h>
+
+ #define ROUNDUP(nbytes, pad) (((((nbytes) - 1) + (pad)) / (pad)) * (pad))
+
+@@ -56,7 +57,7 @@ XImage *XGetImage (
+ xGetImageReply rep;
+ register xGetImageReq *req;
+ char *data;
+- long nbytes;
++ unsigned long nbytes;
+ XImage *image;
+ LockDisplay(dpy);
+ GetReq (GetImage, req);
+@@ -78,10 +79,13 @@ XImage *XGetImage (
+ return (XImage *)NULL;
+ }
+
+- nbytes = (long)rep.length << 2;
+- data = (char *) Xmalloc((unsigned) nbytes);
++ if (rep.length < (INT_MAX >> 2)) {
++ nbytes = (unsigned long)rep.length << 2;
++ data = Xmalloc(nbytes);
++ } else
++ data = NULL;
+ if (! data) {
+- _XEatData(dpy, (unsigned long) nbytes);
++ _XEatDataWords(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return (XImage *) NULL;
+--
+1.7.9.2
+
+From 83f1fc4205d2c9c886bdc4bdab2a27cb0e280110 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Mar 2013 15:08:21 -0800
+Subject: [PATCH:libX11 28/38] integer overflow in XGetPointerMapping() &
+ XGetKeyboardMapping() [CVE-2013-1981 12/13]
+
+Ensure that we don't underallocate when the server claims a very large reply
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/GetPntMap.c | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+diff --git a/src/GetPntMap.c b/src/GetPntMap.c
+index 0fcdb66..29fdf21 100644
+--- a/src/GetPntMap.c
++++ b/src/GetPntMap.c
+@@ -29,6 +29,7 @@ in this Software without prior written authorization from The Open Group.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
+
+ #ifdef MIN /* some systems define this in <sys/param.h> */
+ #undef MIN
+@@ -42,7 +43,7 @@ int XGetPointerMapping (
+
+ {
+ unsigned char mapping[256]; /* known fixed size */
+- long nbytes, remainder = 0;
++ unsigned long nbytes, remainder = 0;
+ xGetPointerMappingReply rep;
+ register xReq *req;
+
+@@ -54,9 +55,15 @@ int XGetPointerMapping (
+ return 0;
+ }
+
+- nbytes = (long)rep.length << 2;
+-
+ /* Don't count on the server returning a valid value */
++ if (rep.length >= (INT_MAX >> 2)) {
++ _XEatDataWords(dpy, rep.length);
++ UnlockDisplay(dpy);
++ SyncHandle();
++ return 0;
++ }
++
++ nbytes = (unsigned long) rep.length << 2;
+ if (nbytes > sizeof mapping) {
+ remainder = nbytes - sizeof mapping;
+ nbytes = sizeof mapping;
+@@ -69,7 +76,7 @@ int XGetPointerMapping (
+ }
+
+ if (remainder)
+- _XEatData(dpy, (unsigned long)remainder);
++ _XEatData(dpy, remainder);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+@@ -86,8 +93,8 @@ XGetKeyboardMapping (Display *dpy,
+ int count,
+ int *keysyms_per_keycode)
+ {
+- long nbytes;
+- unsigned long nkeysyms;
++ unsigned long nbytes;
++ CARD32 nkeysyms;
+ register KeySym *mapping = NULL;
+ xGetKeyboardMappingReply rep;
+ register xGetKeyboardMappingReq *req;
+@@ -102,17 +109,19 @@ XGetKeyboardMapping (Display *dpy,
+ return (KeySym *) NULL;
+ }
+
+- nkeysyms = (unsigned long) rep.length;
++ nkeysyms = rep.length;
+ if (nkeysyms > 0) {
+- nbytes = nkeysyms * sizeof (KeySym);
+- mapping = (KeySym *) Xmalloc ((unsigned) nbytes);
+- nbytes = nkeysyms << 2;
++ if (nkeysyms < (INT_MAX / sizeof (KeySym))) {
++ nbytes = nkeysyms * sizeof (KeySym);
++ mapping = Xmalloc (nbytes);
++ }
+ if (! mapping) {
+- _XEatData(dpy, (unsigned long) nbytes);
++ _XEatDataWords(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return (KeySym *) NULL;
+ }
++ nbytes = nkeysyms << 2;
+ _XRead32 (dpy, (long *) mapping, nbytes);
+ }
+ *keysyms_per_keycode = rep.keySymsPerKeyCode;
+--
+1.7.9.2
+
+From b2e9b2585a4528e23df9f9067c6c6c91115ae55b Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Mar 2013 15:08:21 -0800
+Subject: [PATCH:libX11 29/38] integer overflow in XGetModifierMapping()
+ [CVE-2013-1981 13/13]
+
+Ensure that we don't underallocate when the server claims a very large reply
+
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/ModMap.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/src/ModMap.c b/src/ModMap.c
+index c99bfdd..122ca80 100644
+--- a/src/ModMap.c
++++ b/src/ModMap.c
+@@ -28,6 +28,7 @@ in this Software without prior written authorization from The Open Group.
+ #include <config.h>
+ #endif
+ #include "Xlibint.h"
++#include <limits.h>
+
+ XModifierKeymap *
+ XGetModifierMapping(register Display *dpy)
+@@ -41,13 +42,17 @@ XGetModifierMapping(register Display *dpy)
+ GetEmptyReq(GetModifierMapping, req);
+ (void) _XReply (dpy, (xReply *)&rep, 0, xFalse);
+
+- nbytes = (unsigned long)rep.length << 2;
+- res = (XModifierKeymap *) Xmalloc(sizeof (XModifierKeymap));
+- if (res) res->modifiermap = (KeyCode *) Xmalloc ((unsigned) nbytes);
++ if (rep.length < (LONG_MAX >> 2)) {
++ nbytes = (unsigned long)rep.length << 2;
++ res = Xmalloc(sizeof (XModifierKeymap));
++ if (res)
++ res->modifiermap = Xmalloc (nbytes);
++ } else
++ res = NULL;
+ if ((! res) || (! res->modifiermap)) {
+ if (res) Xfree((char *) res);
+ res = (XModifierKeymap *) NULL;
+- _XEatData(dpy, nbytes);
++ _XEatDataWords(dpy, rep.length);
+ } else {
+ _XReadPad(dpy, (char *) res->modifiermap, (long) nbytes);
+ res->max_keypermod = rep.numKeyPerModifier;
+--
+1.7.9.2
+
+From 3fb82a4726114c1e9916658dad659a4dbfb050c8 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 9 Mar 2013 11:04:37 -0800
+Subject: [PATCH:libX11 33/38] Make XGetWindowProperty() always initialize
+ returned values
+
+Avoids memory corruption and other errors when callers access them
+without checking to see if XGetWindowProperty() returned an error value.
+
+Callers are still required to check for errors, this just reduces the
+damage when they don't.
+
+Reported-by: Ilja Van Sprundel <[email protected]>
+Signed-off-by: Alan Coopersmith <[email protected]>
+Reviewed-by: Matthieu Herrb <[email protected]>
+---
+ src/GetProp.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/GetProp.c b/src/GetProp.c
+index ae14edc..9eb422e 100644
+--- a/src/GetProp.c
++++ b/src/GetProp.c
+@@ -49,6 +49,13 @@ XGetWindowProperty(
+ register xGetPropertyReq *req;
+ xError error = {0};
+
++ /* Always initialize return values, in case callers fail to initialize
++ them and fail to check the return code for an error. */
++ *actual_type = None;
++ *actual_format = 0;
++ *nitems = *bytesafter = 0L;
++ *prop = (unsigned char *) NULL;
++
+ LockDisplay(dpy);
+ GetReq (GetProperty, req);
+ req->window = w;
+@@ -65,7 +72,6 @@ XGetWindowProperty(
+ return (1); /* not Success */
+ }
+
+- *prop = (unsigned char *) NULL;
+ if (reply.propertyType != None) {
+ unsigned long nbytes, netbytes;
+ int format = reply.format;
+--
+1.7.9.2
+