Submitted By: Kelledin <kelledin@users.sourceforge.net>
Date: 2003-09-27
Initial Package Version: 4.3.0
Origin: XFree86-CVS
Synopsis: integer overflow patch for XFree86
Description: XFree86 4.3.0 contains several integer overflow vulnerabilities
             in its Xft handling.  This patch is a backport of various CVS
             entries (authored by blexim and Matthieu Herrb) to fix the issue.


diff -Naur xc/lib/FS/FSFontInfo.c xc-xft/lib/FS/FSFontInfo.c
--- xc/lib/FS/FSFontInfo.c	2001-12-14 13:53:32.000000000 -0600
+++ xc-xft/lib/FS/FSFontInfo.c	2003-09-26 12:50:34.000000000 -0500
@@ -65,7 +65,7 @@
     long        nbytes;
     int         i,
                 j;
-    int         size = 0;
+    size_t      size = 0;
     FSXFontInfoHeader **fhdr = (FSXFontInfoHeader **) 0;
     FSPropInfo **pi = (FSPropInfo **) 0;
     FSPropOffset **po = (FSPropOffset **) 0;
@@ -123,8 +123,14 @@
 	if (reply.nameLength == 0)	/* got last reply in version 1 */
 	    break;
 	if ((i + reply.nReplies) >= size) {
+
+	    if (reply.nReplies > SIZE_MAX - i - 1)
+		goto badmem;
 	    size = i + reply.nReplies + 1;
 
+	    if (size > SIZE_MAX / sizeof(char *))
+		goto badmem;
+
 	    if (fhdr) {
 		FSXFontInfoHeader **tmp_fhdr = (FSXFontInfoHeader **)
 		FSrealloc((char *) fhdr,
@@ -237,6 +243,9 @@
 	pi[i]->num_offsets = local_pi.num_offsets;
 	pi[i]->data_len = local_pi.data_len;
 
+	if (pi[i]->num_offsets > SIZE_MAX / sizeof(FSPropOffset))
+	   goto badmem;
+
 	po[i] = (FSPropOffset *)
 	    FSmalloc(pi[i]->num_offsets * sizeof(FSPropOffset));
 	if (!po[i]) {
@@ -282,6 +291,10 @@
 	    nbytes = pi[i]->data_len + reply.nameLength;
 	    _FSEatData(svr, (unsigned long) (((nbytes+3)&~3) - nbytes));
 	}
+	/* avoid integer overflow */
+	if (i > INT_MAX - 1) {
+	    goto badmem;
+	}
     }
     *info = fhdr;
     *count = i;
diff -Naur xc/lib/FS/FSFtNames.c xc-xft/lib/FS/FSFtNames.c
--- xc/lib/FS/FSFtNames.c	2001-12-14 13:53:32.000000000 -0600
+++ xc-xft/lib/FS/FSFtNames.c	2003-09-26 12:54:56.000000000 -0500
@@ -78,7 +78,8 @@
 	  (SIZEOF(fsListFontsReply) - SIZEOF(fsGenericReply)) >> 2, fsFalse))
 	return (char **) 0;
 
-    if (rep.nFonts) {
+    if (rep.nFonts && rep.nFonts <= SIZE_MAX / sizeof(char *)
+	&& rep.length <= (SIZE_MAX >> 2)) {
 	flist = (char **) FSmalloc((unsigned) rep.nFonts * sizeof(char *));
 	rlen = (rep.length << 2) - SIZEOF(fsListFontsReply);
 	c = (char *) FSmalloc((unsigned) (rlen + 1));
diff -Naur xc/lib/FS/FSGetCats.c xc-xft/lib/FS/FSGetCats.c
--- xc/lib/FS/FSGetCats.c	2001-12-14 13:53:32.000000000 -0600
+++ xc-xft/lib/FS/FSGetCats.c	2003-09-26 12:56:22.000000000 -0500
@@ -72,7 +72,8 @@
 	SyncHandle();
 	return (char **) NULL;
     }
-    if (rep.num_catalogues) {
+    if (rep.num_catalogues && rep.num_catalogues <= SIZE_MAX/sizeof(char *)
+	&& rep.length <= (SIZE_MAX >> 2)) {
 	list = (char **)
 	    FSmalloc((unsigned) (rep.num_catalogues * sizeof(char *)));
 	rlen = (rep.length << 2) - SIZEOF(fsGetCataloguesReply);
diff -Naur xc/lib/FS/FSListCats.c xc-xft/lib/FS/FSListCats.c
--- xc/lib/FS/FSListCats.c	2001-12-14 13:53:32.000000000 -0600
+++ xc-xft/lib/FS/FSListCats.c	2003-09-26 12:57:23.000000000 -0500
@@ -78,7 +78,8 @@
     (SIZEOF(fsListCataloguesReply) - SIZEOF(fsGenericReply)) >> 2, fsFalse))
 	return (char **) 0;
 
-    if (rep.num_catalogues) {
+    if (rep.num_catalogues && rep.num_catalogues <= SIZE_MAX/sizeof(char *)
+	&& rep.length <= (SIZE_MAX>>2)) {
 	clist = (char **)
 	    FSmalloc((unsigned) rep.num_catalogues * sizeof(char *));
 	rlen = (rep.length << 2) - SIZEOF(fsListCataloguesReply);
diff -Naur xc/lib/FS/FSListExt.c xc-xft/lib/FS/FSListExt.c
--- xc/lib/FS/FSListExt.c	2001-12-14 13:53:32.000000000 -0600
+++ xc-xft/lib/FS/FSListExt.c	2003-09-26 12:58:01.000000000 -0500
@@ -72,7 +72,8 @@
 	SyncHandle();
 	return (char **) NULL;
     }
-    if (rep.nExtensions) {
+    if (rep.nExtensions && rep.nExtensions <= SIZE_MAX / sizeof(char *)
+	&& rep.length <= (SIZE_MAX>>2)) {
 	list = (char **) FSmalloc((unsigned)(rep.nExtensions * sizeof(char *)));
 	rlen = (rep.length << 2) - SIZEOF(fsListExtensionsReply);
 	c = (char *) FSmalloc((unsigned) rlen + 1);
diff -Naur xc/lib/FS/FSOpenServ.c xc-xft/lib/FS/FSOpenServ.c
--- xc/lib/FS/FSOpenServ.c	2001-12-14 13:53:33.000000000 -0600
+++ xc-xft/lib/FS/FSOpenServ.c	2003-09-26 12:50:37.000000000 -0500
@@ -118,7 +118,7 @@
     AlternateServer *alts;
     int         altlen;
     char       *vendor_string;
-    long        setuplength;
+    unsigned long        setuplength;
 
     if (server == NULL || *server == '\0') {
 	if ((server = getenv("FONTSERVER")) == NULL) {
@@ -153,7 +153,8 @@
     _FSRead(svr, (char *) &prefix, (long) SIZEOF(fsConnSetup));
 
     setuplength = prefix.alternate_len << 2;
-    if ((alt_data = (char *)
+    if (setuplength > (SIZE_MAX>>2)
+	|| (alt_data = (char *)
 	 (setup = FSmalloc((unsigned) setuplength))) == NULL) {
 	errno = ENOMEM;
 	FSfree((char *) svr);
@@ -162,6 +163,10 @@
     _FSRead(svr, (char *) alt_data, setuplength);
     ad = alt_data;
 
+    if (prefix.num_alternates > SIZE_MAX / sizeof(AlternateServer)) {
+	errno=ENOMEM;
+	return (FSServer *) 0;
+    }
     alts = (AlternateServer *)
 	FSmalloc(sizeof(AlternateServer) * prefix.num_alternates);
     if (!alts) {
@@ -193,7 +198,8 @@
     svr->num_alternates = prefix.num_alternates;
 
     setuplength = prefix.auth_len << 2;
-    if ((auth_data = (char *)
+    if (prefix.auth_len > (SIZE_MAX>>2)
+	|| (auth_data = (char *)
 	 (setup = FSmalloc((unsigned) setuplength))) == NULL) {
 	errno = ENOMEM;
 	FSfree((char *) svr);
diff -Naur xc/lib/FS/FSQGlyphs.c xc-xft/lib/FS/FSQGlyphs.c
--- xc/lib/FS/FSQGlyphs.c	2001-12-14 13:53:33.000000000 -0600
+++ xc-xft/lib/FS/FSQGlyphs.c	2003-09-26 12:50:38.000000000 -0500
@@ -85,12 +85,20 @@
      (SIZEOF(fsQueryXBitmaps8Reply) - SIZEOF(fsGenericReply)) >> 2, fsFalse))
 	return FSBadAlloc;
 
+    if (reply.num_chars > SIZE_MAX / sizeof(FSOffset))
+	return FSBadAlloc;
+
     offs = (FSOffset *) FSmalloc(sizeof(FSOffset) * reply.num_chars);
     *offsets = offs;
     if (!offs)
 	return FSBadAlloc;
     left = (reply.length << 2) - SIZEOF(fsQueryXBitmaps8Reply)
 	- (SIZEOF(fsOffset32) * reply.num_chars);
+    /* XXX This thest is incomplete */
+    if (reply.length > (SIZE_MAX >> 2)) {
+	FSfree((char *) offs);
+	return FSBadAlloc;
+    }
     gd = (unsigned char *) FSmalloc(left);
     *glyphdata = gd;
     if (!gd) {
@@ -141,6 +149,8 @@
 	int i;
 	fsChar2b_version1 *swapped_str;
 
+	if (str_len > SIZE_MAX/SIZEOF(fsChar2b_version1))
+	    return FSBadAlloc;
 	swapped_str = (fsChar2b_version1 *)
 	    FSmalloc(SIZEOF(fsChar2b_version1) * str_len);
 	if (!swapped_str)
@@ -160,12 +170,19 @@
 		  fsFalse))
 	return FSBadAlloc;
 
+    if (reply.num_chars > SIZE_MAX/sizeof(FSOffset))
+	return FSBadAlloc;
     offs = (FSOffset *) FSmalloc(sizeof(FSOffset) * reply.num_chars);
     *offsets = offs;
     if (!offs)
 	return FSBadAlloc;
     left = (reply.length << 2) - SIZEOF(fsQueryXBitmaps16Reply)
 	- (SIZEOF(fsOffset32) * reply.num_chars);
+    /* XXX - this test is incomplete */
+    if (reply.length > (SIZE_MAX>>2)) {
+	FSfree((char *) offs);
+	return FSBadAlloc;
+    }
     gd = (unsigned char *) FSmalloc(left);
     *glyphdata = gd;
     if (!gd) {
diff -Naur xc/lib/FS/FSQXExt.c xc-xft/lib/FS/FSQXExt.c
--- xc/lib/FS/FSQXExt.c	2001-12-14 13:53:33.000000000 -0600
+++ xc-xft/lib/FS/FSQXExt.c	2003-09-26 12:50:38.000000000 -0500
@@ -93,6 +93,9 @@
 		  fsFalse))
 	return FSBadAlloc;
 
+    if (reply.num_extents > SIZE_MAX / sizeof(FSXCharInfo))
+	return FSBadAlloc;
+
     ext = (FSXCharInfo *) FSmalloc(sizeof(FSXCharInfo) * reply.num_extents);
     *extents = ext;
     if (!ext)
@@ -149,6 +152,9 @@
 		  fsFalse))
 	return FSBadAlloc;
 
+    if (reply.num_extents > SIZE_MAX/sizeof(FSXCharInfo))
+	return FSBadAlloc;
+
     ext = (FSXCharInfo *) FSmalloc(sizeof(FSXCharInfo) * reply.num_extents);
     *extents = ext;
     if (!ext)
diff -Naur xc/lib/FS/FSQXInfo.c xc-xft/lib/FS/FSQXInfo.c
--- xc/lib/FS/FSQXInfo.c	2001-12-14 13:53:33.000000000 -0600
+++ xc-xft/lib/FS/FSQXInfo.c	2003-09-26 12:50:38.000000000 -0500
@@ -91,6 +91,9 @@
     props->num_offsets = local_pi.num_offsets;
     props->data_len = local_pi.data_len;
 
+    if (props->num_offsets > SIZE_MAX / sizeof(FSPropOffset))
+	return FSBadAlloc;
+
     /* prepare for prop data */
     offset_data = (FSPropOffset *)
 	FSmalloc(props->num_offsets * sizeof(FSPropOffset));
diff -Naur xc/lib/FS/FSlibos.h xc-xft/lib/FS/FSlibos.h
--- xc/lib/FS/FSlibos.h	2002-05-31 13:45:39.000000000 -0500
+++ xc-xft/lib/FS/FSlibos.h	2003-09-26 12:50:38.000000000 -0500
@@ -76,6 +76,13 @@
 #undef _POSIX_SOURCE
 #endif
 #endif
+#ifndef SIZE_MAX
+# ifdef ULONG_MAX
+#  define SIZE_MAX ULONG_MAX
+# else
+#  define SIZE_MAX UINT_MAX
+# endif
+#endif
 #ifndef OPEN_MAX
 #ifdef SVR4
 #define OPEN_MAX 256
diff -Naur xc/lib/font/fc/fsconvert.c xc-xft/lib/font/fc/fsconvert.c
--- xc/lib/font/fc/fsconvert.c	2002-09-10 11:14:35.000000000 -0500
+++ xc-xft/lib/font/fc/fsconvert.c	2003-09-26 12:50:38.000000000 -0500
@@ -30,6 +30,16 @@
 #include        <X11/X.h>
 #include 	<X11/Xtrans.h>
 #include	<X11/Xpoll.h>
+
+#include	<limits.h>
+#ifndef SIZE_MAX
+# ifdef ULONG_MAX
+#  define SIZE_MAX ULONG_MAX
+# else
+#  define SIZE_MAX UINT_MAX
+# endif
+#endif
+
 #include	"FS.h"
 #include	"FSproto.h"
 #include	"fontmisc.h"
@@ -102,6 +112,10 @@
 
     nprops = pfi->nprops = pi->num_offsets;
 
+    if (nprops < 0
+	|| nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char)))
+	return -1;
+
     dprop = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops +
 				 sizeof (char) * nprops);
     if (!dprop)
diff -Naur xc/lib/font/fc/fserve.c xc-xft/lib/font/fc/fserve.c
--- xc/lib/font/fc/fserve.c	2002-05-31 13:45:49.000000000 -0500
+++ xc-xft/lib/font/fc/fserve.c	2003-09-26 12:50:38.000000000 -0500
@@ -1508,7 +1508,7 @@
     if (conn->blockState & FS_GIVE_UP)
 	return BadFontName;
     
-    if (namelen > sizeof (buf) - 1)
+    if (namelen <= 0 || namelen > sizeof (buf) - 1)
 	return BadFontName;
     
     /*
diff -Naur xc/lib/font/fc/fslibos.h xc-xft/lib/font/fc/fslibos.h
--- xc/lib/font/fc/fslibos.h	2002-05-31 13:45:49.000000000 -0500
+++ xc-xft/lib/font/fc/fslibos.h	2003-09-26 12:50:38.000000000 -0500
@@ -48,13 +48,20 @@
 #ifndef FONT_OPEN_MAX
 
 #ifndef X_NOT_POSIX
-#ifdef _POSIX_SOURCE
-#include <limits.h>
-#else
-#define _POSIX_SOURCE
-#include <limits.h>
-#undef _POSIX_SOURCE
-#endif
+# ifdef _POSIX_SOURCE
+#  include <limits.h>
+# else
+#  define _POSIX_SOURCE
+#  include <limits.h>
+#  undef _POSIX_SOURCE
+# endif
+#endif
+#ifndef SIZE_MAX
+# ifdef ULONG_MAX
+#  define SIZE_MAX ULONG_MAX
+# else
+#  define SIZE_MAX UINT_MAX
+# endif
 #endif
 #ifndef OPEN_MAX
 #if defined(SVR4) || defined(__UNIXOS2__)
