Commit f6c5069a authored by Alan Coopersmith's avatar Alan Coopersmith Committed by Ulrich Sibiller

Avoid overflows in XListFonts() [CVE-2013-1997 13/15]

Ensure that when breaking the returned list into individual strings, we don't walk past the end of allocated memory to write the '\0' bytes Signed-off-by: 's avatarAlan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: 's avatarMatthieu Herrb <matthieu.herrb@laas.fr> Signed-off-by: 's avatarJulien Cristau <jcristau@debian.org> Backported-to-NX-by: 's avatarUlrich Sibiller <uli42@gmx.de>
parent 0284afb8
...@@ -29,6 +29,7 @@ in this Software without prior written authorization from The Open Group. ...@@ -29,6 +29,7 @@ in this Software without prior written authorization from The Open Group.
#include <config.h> #include <config.h>
#endif #endif
#include "Xlibint.h" #include "Xlibint.h"
#include <limits.h>
char ** char **
XListFonts( XListFonts(
...@@ -40,11 +41,13 @@ int *actualCount) /* RETURN */ ...@@ -40,11 +41,13 @@ int *actualCount) /* RETURN */
register long nbytes; register long nbytes;
register unsigned i; register unsigned i;
register int length; register int length;
char **flist; char **flist = NULL;
char *ch; char *ch = NULL;
char *chend;
int count = 0;
xListFontsReply rep; xListFontsReply rep;
register xListFontsReq *req; register xListFontsReq *req;
register long rlen; unsigned long rlen;
LockDisplay(dpy); LockDisplay(dpy);
GetReq(ListFonts, req); GetReq(ListFonts, req);
...@@ -62,15 +65,17 @@ int *actualCount) /* RETURN */ ...@@ -62,15 +65,17 @@ int *actualCount) /* RETURN */
} }
if (rep.nFonts) { if (rep.nFonts) {
flist = (char **)Xmalloc ((unsigned)rep.nFonts * sizeof(char *)); flist = Xmalloc (rep.nFonts * sizeof(char *));
rlen = rep.length << 2; if (rep.length < (LONG_MAX >> 2)) {
ch = (char *) Xmalloc((unsigned) (rlen + 1)); rlen = rep.length << 2;
ch = Xmalloc(rlen + 1);
/* +1 to leave room for last null-terminator */ /* +1 to leave room for last null-terminator */
}
if ((! flist) || (! ch)) { if ((! flist) || (! ch)) {
if (flist) Xfree((char *) flist); if (flist) Xfree((char *) flist);
if (ch) Xfree(ch); if (ch) Xfree(ch);
_XEatData(dpy, (unsigned long) rlen); _XEatDataWords(dpy, rep.length);
*actualCount = 0; *actualCount = 0;
UnlockDisplay(dpy); UnlockDisplay(dpy);
SyncHandle(); SyncHandle();
...@@ -81,17 +86,21 @@ int *actualCount) /* RETURN */ ...@@ -81,17 +86,21 @@ int *actualCount) /* RETURN */
/* /*
* unpack into null terminated strings. * unpack into null terminated strings.
*/ */
chend = ch + (rlen + 1);
length = *(unsigned char *)ch; length = *(unsigned char *)ch;
*ch = 1; /* make sure it is non-zero for XFreeFontNames */ *ch = 1; /* make sure it is non-zero for XFreeFontNames */
for (i = 0; i < rep.nFonts; i++) { for (i = 0; i < rep.nFonts; i++) {
flist[i] = ch + 1; /* skip over length */ if (ch + length < chend) {
ch += length + 1; /* find next length ... */ flist[i] = ch + 1; /* skip over length */
length = *(unsigned char *)ch; ch += length + 1; /* find next length ... */
*ch = '\0'; /* and replace with null-termination */ length = *(unsigned char *)ch;
*ch = '\0'; /* and replace with null-termination */
count++;
} else
flist[i] = NULL;
} }
} }
else flist = (char **) NULL; *actualCount = count;
*actualCount = rep.nFonts;
UnlockDisplay(dpy); UnlockDisplay(dpy);
SyncHandle(); SyncHandle();
return (flist); return (flist);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment