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

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: 's avatarIlja Van Sprundel <ivansprundel@ioactive.com> Signed-off-by: 's avatarAlan Coopersmith <alan.coopersmith@oracle.com> Signed-off-by: 's avatarJulien Cristau <jcristau@debian.org> Backported-to-NX-by: 's avatarUlrich Sibiller <uli42@gmx.de>
parent dda0c652
...@@ -28,6 +28,7 @@ in this Software without prior written authorization from The Open Group. ...@@ -28,6 +28,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>
#if defined(XF86BIGFONT) #if defined(XF86BIGFONT)
#define USE_XF86BIGFONT #define USE_XF86BIGFONT
...@@ -45,10 +46,11 @@ int maxNames, ...@@ -45,10 +46,11 @@ int maxNames,
int *actualCount, /* RETURN */ int *actualCount, /* RETURN */
XFontStruct **info) /* RETURN */ XFontStruct **info) /* RETURN */
{ {
register long nbytes; unsigned long nbytes;
unsigned long reply_left; /* unused data left in reply buffer */
register int i; register int i;
register XFontStruct *fs; register XFontStruct *fs;
register int size = 0; unsigned int size = 0;
XFontStruct *finfo = NULL; XFontStruct *finfo = NULL;
char **flist = NULL; char **flist = NULL;
xListFontsWithInfoReply reply; xListFontsWithInfoReply reply;
...@@ -67,52 +69,44 @@ XFontStruct **info) /* RETURN */ ...@@ -67,52 +69,44 @@ XFontStruct **info) /* RETURN */
if (!_XReply (dpy, (xReply *) &reply, if (!_XReply (dpy, (xReply *) &reply,
((SIZEOF(xListFontsWithInfoReply) - ((SIZEOF(xListFontsWithInfoReply) -
SIZEOF(xGenericReply)) >> 2), xFalse)) { SIZEOF(xGenericReply)) >> 2), xFalse)) {
for (j=(i-1); (j >= 0); j--) { reply.nameLength = 0; /* avoid trying to read more replies */
Xfree(flist[j]); reply_left = 0;
if (finfo[j].properties) Xfree((char *) finfo[j].properties); goto badmem;
}
if (flist) Xfree((char *) flist);
if (finfo) Xfree((char *) finfo);
UnlockDisplay(dpy);
SyncHandle();
return ((char **) NULL);
} }
if (reply.nameLength == 0) reply_left = reply.length -
((SIZEOF(xListFontsWithInfoReply) - SIZEOF(xGenericReply)) >> 2);
if (reply.nameLength == 0) {
_XEatDataWords(dpy, reply_left);
break; break;
}
if (reply.nReplies >= (INT_MAX - i)) /* avoid overflowing size */
goto badmem;
if ((i + reply.nReplies) >= size) { if ((i + reply.nReplies) >= size) {
size = i + reply.nReplies + 1; size = i + reply.nReplies + 1;
if (size >= (INT_MAX / sizeof(XFontStruct)))
goto badmem;
if (finfo) { if (finfo) {
XFontStruct * tmp_finfo = (XFontStruct *) XFontStruct * tmp_finfo;
Xrealloc ((char *) finfo, char ** tmp_flist;
(unsigned) (sizeof(XFontStruct) * size));
char ** tmp_flist = (char **)
Xrealloc ((char *) flist,
(unsigned) (sizeof(char *) * (size+1)));
tmp_finfo = Xrealloc (finfo, sizeof(XFontStruct) * size);
if (tmp_finfo) if (tmp_finfo)
finfo = tmp_finfo; finfo = tmp_finfo;
else
goto badmem;
tmp_flist = Xrealloc (flist, sizeof(char *) * (size+1));
if (tmp_flist) if (tmp_flist)
flist = tmp_flist; flist = tmp_flist;
else
if ((! tmp_finfo) || (! tmp_flist)) { goto badmem;
/* 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 { else {
if (! (finfo = (XFontStruct *) if (! (finfo = Xmalloc(sizeof(XFontStruct) * size)))
Xmalloc((unsigned) (sizeof(XFontStruct) * size))))
goto clearwire; goto clearwire;
if (! (flist = (char **) if (! (flist = Xmalloc(sizeof(char *) * (size+1)))) {
Xmalloc((unsigned) (sizeof(char *) * (size+1))))) {
Xfree((char *) finfo); Xfree((char *) finfo);
goto clearwire; goto clearwire;
} }
...@@ -138,24 +132,27 @@ XFontStruct **info) /* RETURN */ ...@@ -138,24 +132,27 @@ XFontStruct **info) /* RETURN */
fs->max_bounds = * (XCharStruct *) &reply.maxBounds; fs->max_bounds = * (XCharStruct *) &reply.maxBounds;
fs->n_properties = reply.nFontProps; fs->n_properties = reply.nFontProps;
fs->properties = NULL;
if (fs->n_properties > 0) { if (fs->n_properties > 0) {
nbytes = reply.nFontProps * sizeof(XFontProp); /* nFontProps is a CARD16 */
if (! (fs->properties = (XFontProp *) Xmalloc((unsigned) nbytes)))
goto badmem;
nbytes = reply.nFontProps * SIZEOF(xFontProp); 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); _XRead32 (dpy, (long *)fs->properties, nbytes);
reply_left -= (nbytes >> 2);
}
} else /* nameLength is a CARD8 */
fs->properties = NULL; nbytes = reply.nameLength + 1;
j = reply.nameLength + 1;
if (!i) if (!i)
j++; /* make first string 1 byte longer, to match XListFonts */ nbytes++; /* make first string 1 byte longer, to match XListFonts */
flist[i] = (char *) Xmalloc ((unsigned int) j); flist[i] = Xmalloc (nbytes);
if (! flist[i]) { if (! flist[i]) {
if (finfo[i].properties) Xfree((char *) finfo[i].properties); if (finfo[i].properties) Xfree((char *) finfo[i].properties);
nbytes = (reply.nameLength + 3) & ~3;
_XEatData(dpy, (unsigned long) nbytes);
goto badmem; goto badmem;
} }
if (!i) { if (!i) {
...@@ -185,19 +182,15 @@ XFontStruct **info) /* RETURN */ ...@@ -185,19 +182,15 @@ XFontStruct **info) /* RETURN */
clearwire: clearwire:
/* Clear the wire. */ /* Clear the wire. */
do { _XEatDataWords(dpy, reply_left);
if (reply.nFontProps) while ((reply.nameLength != 0) &&
_XEatData(dpy, (unsigned long) _XReply(dpy, (xReply *) &reply,
(reply.nFontProps * SIZEOF(xFontProp))); ((SIZEOF(xListFontsWithInfoReply) - SIZEOF(xGenericReply))
nbytes = (reply.nameLength + 3) & ~3; >> 2), xTrue));
_XEatData(dpy, (unsigned long) nbytes);
}
while (_XReply(dpy,(xReply *) &reply, ((SIZEOF(xListFontsWithInfoReply) -
SIZEOF(xGenericReply)) >> 2),
xFalse) && (reply.nameLength != 0));
UnlockDisplay(dpy); UnlockDisplay(dpy);
SyncHandle(); SyncHandle();
*info = NULL;
*actualCount = 0;
return (char **) NULL; return (char **) NULL;
} }
......
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