Commit message: Reject string longer than USHRT_MAX before sending them on the wire

The X protocol uses CARD16 values to represent the length so
this would overflow.

CVE-2021-31535

Signed-off-by: Matthieu Herrb <matthieu@herrb.eu>
CVE: CVE-2021-31535
CWE: CWE-120
Vulnerability description: LookupCol.c in X.Org X through X11R7.7 and libX11 before 1.7.1 might allow remote attackers to execute arbitrary code. The libX11 XLookupColor request (intended for server-side color lookup) contains a flaw allowing a client to send color-name requests with a name longer than the maximum size allowed by the protocol (and also longer than the maximum packet size for normal-sized packets). The user-controlled data exceeding the maximum size is then interpreted by the server as additional X protocol requests and executed, e.g., to disable X server authorization completely. For example, if the victim encounters malicious terminal control sequences for color codes, then the attacker may be able to take full control of the running graphical session.

Project: libx11
File: LoadFont.c

XLoadFont (
    register Display *dpy,
    _Xconst char *name)
{
    register long nbytes;
    Font fid;
    register xOpenFontReq *req;

    if (strlen(name) >= USHRT_MAX)
        return (0);

    if (_XF86LoadQueryLocaleFont(dpy, name, (XFontStruct **)0, &fid))
      return fid;

    LockDisplay(dpy);
    GetReq(OpenFont, req);
    nbytes = req->nbytes = name ? (CARD16) strlen(name) : 0;
    req->fid = fid = XAllocID(dpy);
    req->length += (nbytes+3)>>2;
    Data (dpy, name, nbytes);
    UnlockDisplay(dpy);
    SyncHandle();
    return (fid);
       /* can't return (req->fid) since request may have already been sent */
}

Project: libx11
File: SetHints.c

XSetSizeHints(		/* old routine */
	Display *dpy,
	Window w,
	XSizeHints *hints,
        Atom property)
{
	xPropSizeHints prop;
	memset(&prop, 0, sizeof(prop));
	prop.flags = (hints->flags & (USPosition|USSize|PAllHints));
	if (hints->flags & (USPosition|PPosition)) {
	    prop.x = hints->x;
	    prop.y = hints->y;
	}
	if (hints->flags & (USSize|PSize)) {
	    prop.width = hints->width;
	    prop.height = hints->height;
	}
	if (hints->flags & PMinSize) {
	    prop.minWidth = hints->min_width;
	    prop.minHeight = hints->min_height;
	}
	if (hints->flags & PMaxSize) {
	    prop.maxWidth  = hints->max_width;
	    prop.maxHeight = hints->max_height;
	}
	if (hints->flags & PResizeInc) {
	    prop.widthInc = hints->width_inc;
	    prop.heightInc = hints->height_inc;
	}
	if (hints->flags & PAspect) {
	    prop.minAspectX = hints->min_aspect.x;
	    prop.minAspectY = hints->min_aspect.y;
	    prop.maxAspectX = hints->max_aspect.x;
	    prop.maxAspectY = hints->max_aspect.y;
	}
	return XChangeProperty (dpy, w, property, XA_WM_SIZE_HINTS, 32,
				PropModeReplace, (unsigned char *) &prop,
				OldNumPropSizeElements);
}

Project: libx11
File: Font.c

XFreeFont(
    register Display *dpy,
    XFontStruct *fs)
{
    register xResourceReq *req;
    register _XExtension *ext;

    LockDisplay(dpy);
    /* call out to any extensions interested */
    for (ext = dpy->ext_procs; ext; ext = ext->next)
	if (ext->free_Font) (*ext->free_Font)(dpy, fs, &ext->codes);
    GetResReq (CloseFont, fs->fid, req);
    UnlockDisplay(dpy);
    SyncHandle();
    if (fs->per_char) {
#ifdef USE_XF86BIGFONT
	_XF86BigfontFreeFontMetrics(fs);
#else
	Xfree (fs->per_char);
#endif
    }
    _XFreeExtData(fs->ext_data);

    Xfree (fs->properties);
    Xfree (fs);
    return 1;
}

Project: libx11
File: FontNames.c

XFreeFontNames(char **list)
{
	if (list) {
		if (!*(list[0]-1)) { /* from ListFontsWithInfo */
			register char **names;
			for (names = list+1; *names; names++)
				Xfree (*names);
		}
		Xfree (list[0]-1);
		Xfree (list);
	}
	return 1;
}

Project: libx11
File: Font.c

_XF86BigfontCodes (
    register Display *dpy)
{
    XEDataObject dpy_union;
    XExtData *pData;
    XF86BigfontCodes *pCodes;
    char *envval;

    dpy_union.display = dpy;

    /* If the server is known to support the XF86Bigfont extension,
     * return the extension codes. If the server is known to not support
     * the extension, don't bother checking again.
     */
    pData = XFindOnExtensionList(XEHeadOfExtensionList(dpy_union),
				 XF86BigfontNumber);
    if (pData)
	return (XF86BigfontCodes *) pData->private_data;

    pData = Xmalloc(sizeof(XExtData) + sizeof(XF86BigfontCodes));
    if (!pData) {
	/* Out of luck. */
	return (XF86BigfontCodes *) NULL;
    }

    /* See if the server supports the XF86Bigfont extension. */
    envval = getenv("XF86BIGFONT_DISABLE"); /* Let the user disable it. */
    if (envval != NULL && envval[0] != '\0')
	pCodes = NULL;
    else {
	XExtCodes *codes = XInitExtension(dpy, XF86BIGFONTNAME);
	if (codes == NULL)
	    pCodes = NULL;
	else {
	    pCodes = (XF86BigfontCodes *) &pData[1];
	    pCodes->codes = codes;
	}
    }
    pData->number = XF86BigfontNumber;
    pData->private_data = (XPointer) pCodes;
    pData->free_private = _XF86BigfontFreeCodes;
    XAddToExtensionList(XEHeadOfExtensionList(dpy_union), pData);
    if (pCodes) {
	int result;

	/* See if the server supports the XF86BigfontQueryFont request. */
	xXF86BigfontQueryVersionReply reply;
	register xXF86BigfontQueryVersionReq *req;

	LockDisplay(dpy);

	GetReq(XF86BigfontQueryVersion, req);
	req->reqType = pCodes->codes->major_opcode;
	req->xf86bigfontReqType = X_XF86BigfontQueryVersion;

	result = _XReply (dpy, (xReply *) &reply,
		(SIZEOF(xXF86BigfontQueryVersionReply) - SIZEOF(xReply)) >> 2,
		xFalse);

	UnlockDisplay(dpy);
    	SyncHandle();

	if(!result)
	    goto ignore_extension;

	/* No need to provide backward compatibility with version 1.0. It
	   was never widely distributed. */
	if (!(reply.majorVersion > 1
	      || (reply.majorVersion == 1 && reply.minorVersion >= 1)))
	    goto ignore_extension;

	pCodes->serverSignature = reply.signature;
	pCodes->serverCapabilities = reply.capabilities;
    }
    return pCodes;

  ignore_extension:
    /* No need to Xfree(pCodes) or Xfree(pCodes->codes), see
       _XF86BigfontFreeCodes comment. */
    pCodes = (XF86BigfontCodes *) NULL;
    pData->private_data = (XPointer) pCodes;
    return pCodes;
}

Project: libx11
File: Font.c

int _XF86LoadQueryLocaleFont(
   Display *dpy,
   _Xconst char *name,
   XFontStruct **xfp,
   Font *fidp)
{
    int l;
    const char *charset, *p;
    char buf[256];
    XFontStruct *fs;
    XLCd lcd;

    if (!name)
	return 0;
    l = (int) strlen(name);
    if (l < 2 || name[l - 1] != '*' || name[l - 2] != '-' || l >= USHRT_MAX)
	return 0;
    charset = NULL;
    /* next three lines stolen from _XkbGetCharset() */
    lcd = _XlcCurrentLC();
    if ((lcd = _XlcCurrentLC()) != 0)
	charset = XLC_PUBLIC(lcd, encoding_name);
    if (!charset || (p = strrchr(charset, '-')) == 0 || p == charset || p[1] == 0 || (p[1] == '*' && p[2] == 0)) {
	/* prefer latin1 if no encoding found */
	charset = "ISO8859-1";
	p = charset + 7;
    }
    if (l - 2 - (p - charset) < 0)
	return 0;
    if (_XlcNCompareISOLatin1(name + l - 2 - (p - charset), charset, p - charset))
	return 0;
    if (strlen(p + 1) + (size_t) l - 1 >= sizeof(buf) - 1)
	return 0;
    strcpy(buf, name);
    strcpy(buf + l - 1, p + 1);
    fs = XLoadQueryFont(dpy, buf);
    if (!fs)
	return 0;
    if (xfp) {
	*xfp = fs;
	if (fidp)
	    *fidp = fs->fid;
    } else if (fidp) {
	if (fs->per_char) {
#ifdef USE_XF86BIGFONT
	    _XF86BigfontFreeFontMetrics(fs);
#else
	    Xfree (fs->per_char);
#endif
	}
	_XFreeExtData(fs->ext_data);

	Xfree (fs->properties);
	*fidp = fs->fid;
	Xfree (fs);
    } else {
	XFreeFont(dpy, fs);
    }
    return 1;
}

Project: libx11
File: StName.c

XSetIconName (
    register Display *dpy,
    Window w,
    _Xconst char *icon_name)
{
    if (strlen(icon_name) >= USHRT_MAX)
        return 0;
    return XChangeProperty(dpy, w, XA_WM_ICON_NAME, XA_STRING, 8,
                           PropModeReplace, (_Xconst unsigned char *)icon_name,
			   icon_name ? (int) strlen(icon_name) : 0);
}

Project: libx11
File: Font.c

_XF86BigfontFreeNop (
    XExtData *extension)
{
    return 0;
}

Project: libx11
File: SetFPath.c

XSetFontPath (
    register Display *dpy,
    char **directories,
    int ndirs)
{
	register int n = 0;
	register int i;
	register int nbytes;
	char *p;
	register xSetFontPathReq *req;
	int retCode;

        LockDisplay(dpy);
	GetReq (SetFontPath, req);
	req->nFonts = ndirs;
	for (i = 0; i < ndirs; i++) {
		n = (int) ((size_t) n + (safestrlen (directories[i]) + 1));
		if (n >= USHRT_MAX) {
			UnlockDisplay(dpy);
			SyncHandle();
			return 0;
		}
	}
	nbytes = (n + 3) & ~3;
	req->length += nbytes >> 2;
	if ((p = Xmalloc (nbytes))) {
		/*
	 	 * pack into counted strings.
	 	 */
		char	*tmp = p;

		for (i = 0; i < ndirs; i++) {
			register int length = (int) safestrlen (directories[i]);
			*p = length;
			memcpy (p + 1, directories[i], (size_t)length);
			p += length + 1;
		}
		Data (dpy, tmp, nbytes);
		Xfree (tmp);
		retCode = 1;
	}
	else
		retCode = 0;

        UnlockDisplay(dpy);
	SyncHandle();
	return (retCode);
}

Project: libx11
File: SetHints.c

XSetCommand (
	Display *dpy,
	Window w,
	char **argv,
	int argc)
{
	register int i;
	size_t nbytes;
	register char *buf, *bp;
	for (i = 0, nbytes = 0; i < argc; i++) {
		nbytes += safestrlen(argv[i]) + 1;
		if (nbytes >= USHRT_MAX)
                    return 1;
	}
	if ((bp = buf = Xmalloc(nbytes))) {
	    /* copy arguments into single buffer */
	    for (i = 0; i < argc; i++) {
		if (argv[i]) {
		    (void) strcpy(bp, argv[i]);
		    bp += strlen(argv[i]) + 1;
		}
		else
		    *bp++ = '\0';
	    }
	    XChangeProperty (dpy, w, XA_WM_COMMAND, XA_STRING, 8,
			     PropModeReplace, (unsigned char *)buf, nbytes);
	    Xfree(buf);
	}
	return 1;
}

Project: libx11
File: Font.c

XFontStruct *XQueryFont (
    register Display *dpy,
    Font fid)
{
    XFontStruct *font_result;
#ifdef USE_XF86BIGFONT
    XF86BigfontCodes *extcodes = _XF86BigfontCodes(dpy);
#endif

    LockDisplay(dpy);
    font_result = NULL;
#ifdef USE_XF86BIGFONT
    if (extcodes) {
	font_result = _XF86BigfontQueryFont(dpy, extcodes, fid, 0L);
    }
#endif
    if (!font_result)
	font_result = _XQueryFont(dpy, fid, 0L);
    UnlockDisplay(dpy);
    SyncHandle();
    return font_result;
}

Project: libx11
File: SetHints.c

XSetTransientForHint(
	Display *dpy,
	Window w,
	Window propWindow)
{
	return XChangeProperty(dpy, w, XA_WM_TRANSIENT_FOR, XA_WINDOW, 32,
			       PropModeReplace, (unsigned char *) &propWindow, 1);
}

Project: libx11
File: FontNames.c

XListFonts(
register Display *dpy,
_Xconst char *pattern,  /* null-terminated */
int maxNames,
int *actualCount)	/* RETURN */
{
    register long nbytes;
    register unsigned i;
    register int length;
    char **flist = NULL;
    char *ch = NULL;
    char *chstart;
    char *chend;
    int count = 0;
    xListFontsReply rep;
    register xListFontsReq *req;
    unsigned long rlen = 0;

    if (strlen(pattern) >= USHRT_MAX)
        return NULL;

    LockDisplay(dpy);
    GetReq(ListFonts, req);
    req->maxNames = maxNames;
    nbytes = req->nbytes = pattern ? (CARD16) strlen (pattern) : 0;
    req->length += (nbytes + 3) >> 2;
    _XSend (dpy, pattern, nbytes);
    /* use _XSend instead of Data, since following _XReply will flush buffer */

    if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
	*actualCount = 0;
	UnlockDisplay(dpy);
	SyncHandle();
	return (char **) NULL;
    }

    if (rep.nFonts) {
	flist = Xmallocarray (rep.nFonts, sizeof(char *));
	if (rep.length > 0 && rep.length < (INT_MAX >> 2)) {
	    rlen = rep.length << 2;
	    ch = Xmalloc(rlen + 1);
	    /* +1 to leave room for last null-terminator */
	}

	if ((! flist) || (! ch)) {
	    Xfree(flist);
	    Xfree(ch);
	    _XEatDataWords(dpy, rep.length);
	    *actualCount = 0;
	    UnlockDisplay(dpy);
	    SyncHandle();
	    return (char **) NULL;
	}

	_XReadPad (dpy, ch, rlen);
	/*
	 * unpack into null terminated strings.
	 */
	chstart = ch;
	chend = ch + rlen;
	length = *(unsigned char *)ch;
	*ch = 1; /* make sure it is non-zero for XFreeFontNames */
	for (i = 0; i < rep.nFonts; i++) {
	    if (ch + length < chend) {
		flist[i] = ch + 1;  /* skip over length */
		ch += length + 1;  /* find next length ... */
		length = *(unsigned char *)ch;
		*ch = '\0';  /* and replace with null-termination */
		count++;
	    } else {
                Xfree(chstart);
                Xfree(flist);
                flist = NULL;
                count = 0;
                break;
            }
	}
    }
    *actualCount = count;
    UnlockDisplay(dpy);
    SyncHandle();
    return (flist);
}

Project: libx11
File: SetHints.c

XSetClassHint(
	Display *dpy,
	Window w,
	XClassHint *classhint)
{
	char *class_string;
	char *s;
	size_t len_nm, len_cl;

	len_nm = safestrlen(classhint->res_name);
	len_cl = safestrlen(classhint->res_class);
        if (len_nm + len_cl >= USHRT_MAX)
            return 1;
	if ((class_string = s = Xmalloc(len_nm + len_cl + 2))) {
	    if (len_nm) {
		strcpy(s, classhint->res_name);
		s += len_nm + 1;
	    }
	    else
		*s++ = '\0';
	    if (len_cl)
		strcpy(s, classhint->res_class);
	    else
		*s = '\0';
	    XChangeProperty(dpy, w, XA_WM_CLASS, XA_STRING, 8,
			    PropModeReplace, (unsigned char *) class_string,
			    len_nm+len_cl+2);
	    Xfree(class_string);
	}
	return 1;
}

Project: libx11
File: LookupCol.c

XLookupColor (
	register Display *dpy,
        Colormap cmap,
	_Xconst char *spec,
	XColor *def,
	XColor *scr)
{
	register int n;
	xLookupColorReply reply;
	register xLookupColorReq *req;
	XcmsCCC ccc;
	XcmsColor cmsColor_exact;

	n = (int) strlen (spec);
	if (n >= USHRT_MAX)
            return 0;
#ifdef XCMS
	/*
	 * Let's Attempt to use Xcms and i18n approach to Parse Color
	 */
	if ((ccc = XcmsCCCOfColormap(dpy, cmap)) != (XcmsCCC)NULL) {
	    const char *tmpName = spec;

	    switch (_XcmsResolveColorString(ccc, &tmpName, &cmsColor_exact,
					    XcmsRGBFormat)) {
	    case XcmsSuccess:
	    case XcmsSuccessWithCompression:
		_XcmsRGB_to_XColor(&cmsColor_exact, def, 1);
		memcpy((char *)scr, (char *)def, sizeof(XColor));
		_XUnresolveColor(ccc, scr);
		return(1);
	    case XcmsFailure:
	    case _XCMS_NEWNAME:
		/*
		 * if the result was _XCMS_NEWNAME tmpName points to
		 * a string in cmsColNm.c:pairs table, for example,
		 * gray70 would become tekhvc:0.0/70.0/0.0
		 */
		break;
	    }
	}
#endif

	/*
	 * Xcms and i18n methods failed, so lets pass it to the server
	 * for parsing.
	 */
	LockDisplay(dpy);
	GetReq (LookupColor, req);
	req->cmap = cmap;
	req->nbytes = n;
	req->length += (n + 3) >> 2;
	Data (dpy, spec, (long)n);
	if (!_XReply (dpy, (xReply *) &reply, 0, xTrue)) {
	    UnlockDisplay(dpy);
	    SyncHandle();
	    return (0);
	    }
	def->red   = reply.exactRed;
	def->green = reply.exactGreen;
	def->blue  = reply.exactBlue;

	scr->red   = reply.screenRed;
	scr->green = reply.screenGreen;
	scr->blue  = reply.screenBlue;

	UnlockDisplay(dpy);
	SyncHandle();
	return (1);
}

Project: libx11
File: SetHints.c

XSetStandardProperties (
    	Display *dpy,
    	Window w,		/* window to decorate */
    	_Xconst char *name,	/* name of application */
    	_Xconst char *icon_string,/* name string for icon */
	Pixmap icon_pixmap,	/* pixmap to use as icon, or None */
    	char **argv,		/* command to be used to restart application */
    	int argc,		/* count of arguments */
    	XSizeHints *hints)	/* size hints for window in its normal state */
{
	XWMHints phints;
	phints.flags = 0;

	if (name != NULL) XStoreName (dpy, w, name);

        if (safestrlen(icon_string) >= USHRT_MAX)
            return 1;
	if (icon_string != NULL) {
	    XChangeProperty (dpy, w, XA_WM_ICON_NAME, XA_STRING, 8,
                             PropModeReplace,
                             (_Xconst unsigned char *)icon_string,
                             (int)safestrlen(icon_string));
		}

	if (icon_pixmap != None) {
		phints.icon_pixmap = icon_pixmap;
		phints.flags |= IconPixmapHint;
		}
	if (argv != NULL) XSetCommand(dpy, w, argv, argc);

	if (hints != NULL) XSetNormalHints(dpy, w, hints);

	if (phints.flags != 0) XSetWMHints(dpy, w, &phints);

	return 1;
}

Project: libx11
File: GetColor.c

XAllocNamedColor(
register Display *dpy,
Colormap cmap,
_Xconst char *colorname, /* STRING8 */
XColor *hard_def, /* RETURN */
XColor *exact_def) /* RETURN */
{

    long nbytes;
    xAllocNamedColorReply rep;
    xAllocNamedColorReq *req;

    XcmsCCC ccc;
    XcmsColor cmsColor_exact;
    Status ret;

    if (strlen(colorname) >= USHRT_MAX)
        return (0);

#ifdef XCMS
    /*
     * Let's Attempt to use Xcms and i18n approach to Parse Color
     */
    if ((ccc = XcmsCCCOfColormap(dpy, cmap)) != (XcmsCCC)NULL) {
	const char *tmpName = colorname;

	switch (_XcmsResolveColorString(ccc, &tmpName, &cmsColor_exact,
					XcmsRGBFormat)) {
	case XcmsSuccess:
	case XcmsSuccessWithCompression:
	    _XcmsRGB_to_XColor(&cmsColor_exact, exact_def, 1);
	    memcpy((char *)hard_def, (char *)exact_def, sizeof(XColor));
	    ret = XAllocColor(dpy, cmap, hard_def);
	    exact_def->pixel = hard_def->pixel;
	    return(ret);
	case XcmsFailure:
	case _XCMS_NEWNAME:
	    /*
	     * if the result was _XCMS_NEWNAME tmpName points to
	     * a string in cmsColNm.c:pairs table, for example,
	     * gray70 would become tekhvc:0.0/70.0/0.0
	     */
	    break;
	}
    }
#endif

    /*
     * Xcms and i18n approach failed.
     */
    LockDisplay(dpy);
    GetReq(AllocNamedColor, req);

    req->cmap = cmap;
    nbytes = req->nbytes = (CARD16) strlen(colorname);
    req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */

    _XSend(dpy, colorname, nbytes);
       /* _XSend is more efficient that Data, since _XReply follows */

    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
	UnlockDisplay(dpy);
        SyncHandle();
        return (0);
    }

    exact_def->red = rep.exactRed;
    exact_def->green = rep.exactGreen;
    exact_def->blue = rep.exactBlue;

    hard_def->red = rep.screenRed;
    hard_def->green = rep.screenGreen;
    hard_def->blue = rep.screenBlue;

    exact_def->pixel = hard_def->pixel = rep.pixel;

    UnlockDisplay(dpy);
    SyncHandle();
    return (1);
}

Project: libx11
File: Font.c

_XQueryFont (
    register Display *dpy,
    Font fid,
    unsigned long seq)
{
    register XFontStruct *fs;
    unsigned long nbytes;
    unsigned long reply_left; /* unused data words left in reply buffer */
    xQueryFontReply reply;
    register xResourceReq *req;
    register _XExtension *ext;
    _XAsyncHandler async;
    _XAsyncErrorState async_state;

    if (seq) {
	async_state.min_sequence_number = seq;
	async_state.max_sequence_number = seq;
	async_state.error_code = BadName;
	async_state.major_opcode = X_OpenFont;
	async_state.minor_opcode = 0;
	async_state.error_count = 0;
	async.next = dpy->async_handlers;
	async.handler = _XAsyncErrorHandler;
	async.data = (XPointer)&async_state;
	dpy->async_handlers = &async;
    }
    GetResReq(QueryFont, fid, req);
    if (!_XReply (dpy, (xReply *) &reply,
       ((SIZEOF(xQueryFontReply) - SIZEOF(xReply)) >> 2), xFalse)) {
	if (seq)
	    DeqAsyncHandler(dpy, &async);
	return (XFontStruct *)NULL;
    }
    if (seq)
	DeqAsyncHandler(dpy, &async);
    reply_left = reply.length -
	((SIZEOF(xQueryFontReply) - SIZEOF(xReply)) >> 2);
    if (! (fs = Xmalloc (sizeof (XFontStruct)))) {
	_XEatDataWords(dpy, reply_left);
	return (XFontStruct *)NULL;
    }
    fs->ext_data 		= NULL;
    fs->fid 			= fid;
    fs->direction 		= reply.drawDirection;
    fs->min_char_or_byte2	= reply.minCharOrByte2;
    fs->max_char_or_byte2 	= reply.maxCharOrByte2;
    fs->min_byte1 		= reply.minByte1;
    fs->max_byte1 		= reply.maxByte1;
    fs->default_char 		= reply.defaultChar;
    fs->all_chars_exist 	= reply.allCharsExist;
    fs->ascent 			= cvtINT16toInt (reply.fontAscent);
    fs->descent 		= cvtINT16toInt (reply.fontDescent);

    /* XXX the next two statements won't work if short isn't 16 bits */
    fs->min_bounds = * (XCharStruct *) &reply.minBounds;
    fs->max_bounds = * (XCharStruct *) &reply.maxBounds;

    fs->n_properties = reply.nFontProps;
    /*
     * if no properties defined for the font, then it is bad
     * font, but shouldn't try to read nothing.
     */
    fs->properties = NULL;
    if (fs->n_properties > 0) {
	    /* nFontProps is a CARD16 */
	    nbytes = reply.nFontProps * SIZEOF(xFontProp);
	    if ((nbytes >> 2) <= reply_left) {
		fs->properties = Xmallocarray (reply.nFontProps,
                                               sizeof(XFontProp));
	    }
	    if (! fs->properties) {
		Xfree(fs);
		_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
     * shouldn't try to read nothing.
     */
    fs->per_char = NULL;
    if (reply.nCharInfos > 0){
	/* nCharInfos is a CARD32 */
	if (reply.nCharInfos < (INT_MAX / sizeof(XCharStruct))) {
	    nbytes = reply.nCharInfos * SIZEOF(xCharInfo);
	    if ((nbytes >> 2) <= reply_left) {
		fs->per_char = Xmallocarray (reply.nCharInfos,
                                             sizeof(XCharStruct));
	    }
	}
	if (! fs->per_char) {
	    Xfree(fs->properties);
	    Xfree(fs);
	    _XEatDataWords(dpy, reply_left);
	    return (XFontStruct *)NULL;
	}

	_XRead16 (dpy, (char *)fs->per_char, nbytes);
    }

    /* call out to any extensions interested */
    for (ext = dpy->ext_procs; ext; ext = ext->next)
	if (ext->create_Font) (*ext->create_Font)(dpy, fs, &ext->codes);
    return fs;
}

Project: libx11
File: Font.c

XFontStruct *XLoadQueryFont(
   register Display *dpy,
   _Xconst char *name)
{
    XFontStruct *font_result;
    register long nbytes;
    Font fid;
    xOpenFontReq *req;
    unsigned long seq;
#ifdef USE_XF86BIGFONT
    XF86BigfontCodes *extcodes = _XF86BigfontCodes(dpy);
#endif

    if (strlen(name) >= USHRT_MAX)
        return NULL;
    if (_XF86LoadQueryLocaleFont(dpy, name, &font_result, (Font *)0))
      return font_result;
    LockDisplay(dpy);
    GetReq(OpenFont, req);
    seq = dpy->request; /* Can't use extended sequence number here */
    nbytes = req->nbytes = (CARD16) (name ? strlen(name) : 0);
    req->fid = fid = XAllocID(dpy);
    req->length += (nbytes+3)>>2;
    Data (dpy, name, nbytes);
    font_result = NULL;
#ifdef USE_XF86BIGFONT
    if (extcodes) {
	font_result = _XF86BigfontQueryFont(dpy, extcodes, fid, seq);
	seq = 0;
    }
#endif
    if (!font_result)
	font_result = _XQueryFont(dpy, fid, seq);
    UnlockDisplay(dpy);
    SyncHandle();
    return font_result;
}

Project: libx11
File: StNColor.c

XStoreNamedColor(
register Display *dpy,
Colormap cmap,
_Xconst char *name, /* STRING8 */
unsigned long pixel, /* CARD32 */
int flags)  /* DoRed, DoGreen, DoBlue */
{
    unsigned int nbytes;
    register xStoreNamedColorReq *req;
    XcmsCCC ccc;
    XcmsColor cmsColor_exact;
    XColor scr_def;

    if (strlen(name) >= USHRT_MAX)
        return 0;
#ifdef XCMS
    /*
     * Let's Attempt to use Xcms approach to Parse Color
     */
    if ((ccc = XcmsCCCOfColormap(dpy, cmap)) != (XcmsCCC)NULL) {
	if (_XcmsResolveColorString(ccc, &name, &cmsColor_exact,
		XcmsRGBFormat) >= XcmsSuccess) {
	    _XcmsRGB_to_XColor(&cmsColor_exact, &scr_def, 1);
	    scr_def.pixel = pixel;
	    scr_def.flags = flags;
	    return XStoreColor(dpy, cmap, &scr_def);
	}
	/*
	 * Otherwise we failed; or name was changed with yet another
	 * name.  Thus pass name to the X Server.
	 */
    }
#endif

    /*
     * The Xcms and i18n methods failed, so lets pass it to the server
     * for parsing.
     */

    LockDisplay(dpy);
    GetReq(StoreNamedColor, req);

    req->cmap = cmap;
    req->flags = flags;
    req->pixel = pixel;
    req->nbytes = (CARD16) (nbytes = (unsigned) strlen(name));
    req->length += (nbytes + 3) >> 2; /* round up to multiple of 4 */
    Data(dpy, name, (long)nbytes);
    UnlockDisplay(dpy);
    SyncHandle();
    return 0;
}

Project: libx11
File: SetHints.c

XSetWMHints (
	Display *dpy,
	Window w,
	XWMHints *wmhints)
{
	xPropWMHints prop;
	memset(&prop, 0, sizeof(prop));
	prop.flags = wmhints->flags;
	if (wmhints->flags & InputHint)
	    prop.input = (wmhints->input == True ? 1 : 0);
	if (wmhints->flags & StateHint)
	    prop.initialState = wmhints->initial_state;
	if (wmhints->flags & IconPixmapHint)
	    prop.iconPixmap = wmhints->icon_pixmap;
	if (wmhints->flags & IconWindowHint)
	    prop.iconWindow = wmhints->icon_window;
	if (wmhints->flags & IconPositionHint) {
	    prop.iconX = wmhints->icon_x;
	    prop.iconY = wmhints->icon_y;
	}
	if (wmhints->flags & IconMaskHint)
	    prop.iconMask = wmhints->icon_mask;
	if (wmhints->flags & WindowGroupHint)
	    prop.windowGroup = wmhints->window_group;
	return XChangeProperty (dpy, w, XA_WM_HINTS, XA_WM_HINTS, 32,
				PropModeReplace, (unsigned char *) &prop,
				NumPropWMHintsElements);
}

Project: libx11
File: StName.c

XStoreName (
    register Display *dpy,
    Window w,
    _Xconst char *name)
{
    if (strlen(name) >= USHRT_MAX)
        return 0;
    return XChangeProperty(dpy, w, XA_WM_NAME, XA_STRING, /*  */
			   8, PropModeReplace, (_Xconst unsigned char *)name,
			   name ? (int) strlen(name) : 0);
}

Project: libx11
File: ParseCol.c

XParseColor (
	register Display *dpy,
        Colormap cmap,
	_Xconst char *spec,
	XColor *def)
{
	register int n, i;
	int r, g, b;
	char c;
	XcmsCCC ccc;
	XcmsColor cmsColor;

        if (!spec) return(0);
	n = (int) strlen (spec);
	if (n >= USHRT_MAX)
            return(0);
	if (*spec == '#') {
	    /*
	     * RGB
	     */
	    spec++;
	    n--;
	    if (n != 3 && n != 6 && n != 9 && n != 12)
		return (0);
	    n /= 3;
	    g = b = 0;
	    do {
		r = g;
		g = b;
		b = 0;
		for (i = n; --i >= 0; ) {
		    c = *spec++;
		    b <<= 4;
		    if (c >= '0' && c <= '9')
			b |= c - '0';
		    else if (c >= 'A' && c <= 'F')
			b |= c - ('A' - 10);
		    else if (c >= 'a' && c <= 'f')
			b |= c - ('a' - 10);
		    else return (0);
		}
	    } while (*spec != '\0');
	    n <<= 2;
	    n = 16 - n;
	    def->red = r << n;
	    def->green = g << n;
	    def->blue = b << n;
	    def->flags = DoRed | DoGreen | DoBlue;
	    return (1);
	}


#ifdef XCMS
	/*
	 * Let's Attempt to use Xcms and i18n approach to Parse Color
	 */
	if ((ccc = XcmsCCCOfColormap(dpy, cmap)) != (XcmsCCC)NULL) {
	    const char *tmpName = spec;

	    switch (_XcmsResolveColorString(ccc, &tmpName, &cmsColor,
					    XcmsRGBFormat)) {
	    case XcmsSuccess:
	    case XcmsSuccessWithCompression:
		cmsColor.pixel = def->pixel;
		_XcmsRGB_to_XColor(&cmsColor, def, 1);
		return(1);
	    case XcmsFailure:
	    case _XCMS_NEWNAME:
		/*
		 * if the result was _XCMS_NEWNAME tmpName points to
		 * a string in cmsColNm.c:pairs table, for example,
		 * gray70 would become tekhvc:0.0/70.0/0.0
		 */
		break;
	    }
	}
#endif

	/*
	 * Xcms and i18n methods failed, so lets pass it to the server
	 * for parsing.
	 */
	{
	    xLookupColorReply reply;
	    register xLookupColorReq *req;
	    LockDisplay(dpy);
	    GetReq (LookupColor, req);
	    req->cmap = cmap;
	    req->nbytes = (CARD16) (n = (int) strlen(spec));
	    req->length += (n + 3) >> 2;
	    Data (dpy, spec, (long)n);
	    if (!_XReply (dpy, (xReply *) &reply, 0, xTrue)) {
		UnlockDisplay(dpy);
		SyncHandle();
		return (0);
		}
	    def->red = reply.exactRed;
	    def->green = reply.exactGreen;
	    def->blue = reply.exactBlue;
	    def->flags = DoRed | DoGreen | DoBlue;
	    UnlockDisplay(dpy);
	    SyncHandle();
	    return (1);
	}
}

Project: libx11
File: Font.c

_XF86BigfontQueryFont (
    register Display *dpy,
    XF86BigfontCodes *extcodes,
    Font fid,
    unsigned long seq)
{
    register XFontStruct *fs;
    unsigned long nbytes;
    unsigned long reply_left; /* unused data left in reply buffer */
    xXF86BigfontQueryFontReply reply;
    register xXF86BigfontQueryFontReq *req;
    register _XExtension *ext;
    _XAsyncHandler async1;
    _XAsyncErrorState async1_state;
    _XAsyncHandler async2;
    _XAsyncErrorState async2_state;

    if (seq) {
	async1_state.min_sequence_number = seq;
	async1_state.max_sequence_number = seq;
	async1_state.error_code = BadName;
	async1_state.major_opcode = X_OpenFont;
	async1_state.minor_opcode = 0;
	async1_state.error_count = 0;
	async1.next = dpy->async_handlers;
	async1.handler = _XAsyncErrorHandler;
	async1.data = (XPointer)&async1_state;
	dpy->async_handlers = &async1;
    }

    GetReq(XF86BigfontQueryFont, req);
    req->reqType = extcodes->codes->major_opcode;
    req->xf86bigfontReqType = X_XF86BigfontQueryFont;
    req->id = fid;
    req->flags = (extcodes->serverCapabilities & XF86Bigfont_CAP_LocalShm
		  ? XF86Bigfont_FLAGS_Shm : 0);

    /* The function _XQueryFont benefits from a "magic" error handler for
       BadFont coming from a X_QueryFont request. (See function _XReply.)
       We have to establish an error handler ourselves. */
    async2_state.min_sequence_number = dpy->request;
    async2_state.max_sequence_number = dpy->request;
    async2_state.error_code = BadFont;
    async2_state.major_opcode = extcodes->codes->major_opcode;
    async2_state.minor_opcode = X_XF86BigfontQueryFont;
    async2_state.error_count = 0;
    async2.next = dpy->async_handlers;
    async2.handler = _XAsyncErrorHandler;
    async2.data = (XPointer)&async2_state;
    dpy->async_handlers = &async2;

    if (!_XReply (dpy, (xReply *) &reply,
       ((SIZEOF(xXF86BigfontQueryFontReply) - SIZEOF(xReply)) >> 2), xFalse)) {
	DeqAsyncHandler(dpy, &async2);
	if (seq)
	    DeqAsyncHandler(dpy, &async1);
	return (XFontStruct *)NULL;
    }
    DeqAsyncHandler(dpy, &async2);
    if (seq)
	DeqAsyncHandler(dpy, &async1);
    reply_left = reply.length -
	((SIZEOF(xXF86BigfontQueryFontReply) - SIZEOF(xReply)) >> 2);
    if (! (fs = Xmalloc (sizeof (XFontStruct)))) {
	_XEatDataWords(dpy, reply_left);
	return (XFontStruct *)NULL;
    }
    fs->ext_data 		= NULL;
    fs->fid 			= fid;
    fs->direction 		= reply.drawDirection;
    fs->min_char_or_byte2	= reply.minCharOrByte2;
    fs->max_char_or_byte2 	= reply.maxCharOrByte2;
    fs->min_byte1 		= reply.minByte1;
    fs->max_byte1 		= reply.maxByte1;
    fs->default_char 		= reply.defaultChar;
    fs->all_chars_exist 	= reply.allCharsExist;
    fs->ascent 			= cvtINT16toInt (reply.fontAscent);
    fs->descent 		= cvtINT16toInt (reply.fontDescent);

    /* XXX the next two statements won't work if short isn't 16 bits */
    fs->min_bounds = * (XCharStruct *) &reply.minBounds;
    fs->max_bounds = * (XCharStruct *) &reply.maxBounds;

    fs->n_properties = reply.nFontProps;
    /*
     * if no properties defined for the font, then it is bad
     * font, but shouldn't try to read nothing.
     */
    fs->properties = NULL;
    if (fs->n_properties > 0) {
	/* nFontProps is a CARD16 */
	nbytes = reply.nFontProps * SIZEOF(xFontProp);
	if ((nbytes >> 2) <= reply_left) {
	    fs->properties = Xmallocarray (reply.nFontProps,
                                           sizeof(XFontProp));
	}
	if (! fs->properties) {
	    Xfree(fs);
	    _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(fs->properties);
	Xfree(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)) {
	    xCharInfo* pUniqCI;
	    CARD16* pIndex2UniqIndex;
	    int i;

	    nbytes = reply.nUniqCharInfos * SIZEOF(xCharInfo)
	             + (reply.nCharInfos+1)/2 * 2 * sizeof(CARD16);
	    pUniqCI = Xmalloc (nbytes);
	    if (!pUniqCI) {
		Xfree(fs->properties);
		Xfree(fs);
		_XEatDataWords(dpy, reply_left);
		return (XFontStruct *)NULL;
	    }
	    if (! (fs->per_char = Xmallocarray (reply.nCharInfos,
                                                sizeof(XCharStruct)))) {
		Xfree(pUniqCI);
		Xfree(fs->properties);
		Xfree(fs);
		_XEatDataWords(dpy, reply_left);
		return (XFontStruct *)NULL;
	    }
	    _XRead16 (dpy, (char *) pUniqCI, nbytes);
	    pIndex2UniqIndex = (CARD16*) (pUniqCI + reply.nUniqCharInfos);
	    for (i = 0; i < reply.nCharInfos; i++) {
		if (pIndex2UniqIndex[i] >= reply.nUniqCharInfos) {
		    fprintf(stderr, "_XF86BigfontQueryFont: server returned wrong data\n");
		    Xfree(pUniqCI);
		    Xfree(fs->properties);
		    Xfree(fs);
		    return (XFontStruct *)NULL;
		}
		/* XXX the next statement won't work if short isn't 16 bits */
		fs->per_char[i] = * (XCharStruct *) &pUniqCI[pIndex2UniqIndex[i]];
	    }
	    Xfree(pUniqCI);
	} else {
#ifdef HAS_SHM
	    XExtData *pData;
	    XEDataObject fs_union;
	    char *addr;

	    pData = Xmalloc(sizeof(XExtData));
	    if (!pData) {
		Xfree(fs->properties);
		Xfree(fs);
		return (XFontStruct *)NULL;
	    }

	    /* In some cases (e.g. an ssh daemon forwarding an X session to
	       a remote machine) it is possible that the X server thinks we
	       are running on the same machine (because getpeername() and
	       LocalClient() cannot know about the forwarding) but we are
	       not really local. Therefore, when we attach the first shared
	       memory segment, we verify that we are on the same machine as
	       the X server by checking that 1. shmat() succeeds, 2. the
	       segment has a sufficient size, 3. it contains the X server's
	       signature. Then we set the CAP_VerifiedLocal bit to indicate
	       the verification was successful. */

	    if ((addr = shmat(reply.shmid, NULL, SHM_RDONLY)) == (char *)-1) {
		if (extcodes->serverCapabilities & CAP_VerifiedLocal)
		    fprintf(stderr, "_XF86BigfontQueryFont: could not attach shm segment\n");
	        Xfree(pData);
	        Xfree(fs->properties);
	        Xfree(fs);
		/* Stop requesting shared memory transport from now on. */
		extcodes->serverCapabilities &= ~ XF86Bigfont_CAP_LocalShm;
	        return (XFontStruct *)NULL;
	    }

	    if (!(extcodes->serverCapabilities & CAP_VerifiedLocal)) {
		struct shmid_ds buf;
		if (!(shmctl(reply.shmid, IPC_STAT, &buf) >= 0
		      && reply.nCharInfos < (INT_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);
		    Xfree(pData);
		    Xfree(fs->properties);
		    Xfree(fs);
		    /* Stop requesting shared memory transport from now on. */
		    extcodes->serverCapabilities &= ~ XF86Bigfont_CAP_LocalShm;
		    return (XFontStruct *)NULL;
		}
		extcodes->serverCapabilities |= CAP_VerifiedLocal;
	    }

	    pData->number = XF86BigfontNumber;
	    pData->private_data = (XPointer) addr;
	    pData->free_private = _XF86BigfontFreeNop;
	    fs_union.font = fs;
	    XAddToExtensionList(XEHeadOfExtensionList(fs_union), pData);

	    fs->per_char = (XCharStruct *) (addr + reply.shmsegoffset);
#else
	    fprintf(stderr, "_XF86BigfontQueryFont: try recompiling libX11 with HasShm, Xserver has shm support\n");
	    if (fs->properties) Xfree(fs->properties);
	    Xfree(fs);
	    /* Stop requesting shared memory transport from now on. */
	    extcodes->serverCapabilities &= ~ XF86Bigfont_CAP_LocalShm;
	    return (XFontStruct *)NULL;
#endif
	}
    }

    /* call out to any extensions interested */
    for (ext = dpy->ext_procs; ext; ext = ext->next)
	if (ext->create_Font) (*ext->create_Font)(dpy, fs, &ext->codes);
    return fs;
}

Project: libx11
File: Font.c

_XF86BigfontFreeFontMetrics (XFontStruct *fs)
{
#ifdef HAS_SHM
    XExtData *pData;
    XEDataObject fs_union;

    fs_union.font = fs;
    if ((pData = XFindOnExtensionList(XEHeadOfExtensionList(fs_union),
				      XF86BigfontNumber)))
	shmdt ((char *) pData->private_data);
    else
	Xfree (fs->per_char);
#else
    Xfree (fs->per_char);
#endif
}

Project: libx11
File: Font.c

_XF86BigfontFreeCodes (
    XExtData *extension)
{
    /* Don't Xfree(extension->private_data) because it is on the same malloc
       chunk as extension. */
    /* Don't Xfree(extension->private_data->codes) because this is shared with
       the display's ext_procs list. */
    return 0;
}

Project: libx11
File: SetHints.c

XSetNormalHints (			/* old routine */
	Display *dpy,
	Window w,
	XSizeHints *hints)
{
	return XSetSizeHints (dpy, w, hints, XA_WM_NORMAL_HINTS);
}

Project: libx11
File: FontInfo.c

XFreeFontInfo (
    char **names,
    XFontStruct *info,
    int actualCount)
{
	register int i;
	if (names) {
		Xfree (names[0]-1);
		for (i = 1; i < actualCount; i++) {
			Xfree (names[i]);
		}
		Xfree(names);
	}
	if (info) {
		for (i = 0; i < actualCount; i++) {
			if (info[i].per_char)
#ifdef USE_XF86BIGFONT
				_XF86BigfontFreeFontMetrics(&info[i]);
#else
				Xfree (info[i].per_char);
#endif
			if (info[i].properties)
				Xfree (info[i].properties);
			}
		Xfree(info);
	}
	return 1;
}

Project: libx11
File: QuExt.c

XQueryExtension(
    register Display *dpy,
    _Xconst char *name,
    int *major_opcode,  /* RETURN */
    int *first_event,   /* RETURN */
    int *first_error)	/* RETURN */
{
    xQueryExtensionReply rep;
    register xQueryExtensionReq *req;

    if (strlen(name) >= USHRT_MAX)
        return false;

    LockDisplay(dpy);
    GetReq(QueryExtension, req);
    req->nbytes = name ? (CARD16) strlen(name) : 0;
    req->length += (req->nbytes+(unsigned)3)>>2;
    _XSend(dpy, name, (long)req->nbytes);
    (void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
    *major_opcode = rep.major_opcode;
    *first_event = rep.first_event;
    *first_error = rep.first_error;
    UnlockDisplay(dpy);
    SyncHandle();
    return (rep.present);
}

Project: libx11
File: SetHints.c

XSetZoomHints (
	Display *dpy,
	Window w,
	XSizeHints *zhints)
{
	return XSetSizeHints (dpy, w, zhints, XA_WM_ZOOM_HINTS);
}

Project: libx11
File: SetHints.c

XSetIconSizes (
	Display *dpy,
	Window w,	/* typically, root */
	XIconSize *list,
	int count) 	/* number of items on the list */
{
	register int i;
	xPropIconSize *pp, *prop;

	if ((prop = pp = Xmallocarray (count, sizeof(xPropIconSize)))) {
	    for (i = 0; i < count; i++) {
		pp->minWidth  = list->min_width;
		pp->minHeight = list->min_height;
		pp->maxWidth  = list->max_width;
		pp->maxHeight = list->max_height;
		pp->widthInc  = list->width_inc;
		pp->heightInc = list->height_inc;
		pp += 1;
		list += 1;
	    }
	    XChangeProperty (dpy, w, XA_WM_ICON_SIZE, XA_WM_ICON_SIZE, 32,
			     PropModeReplace, (unsigned char *) prop,
			     count * NumPropIconSizeElements);
	    Xfree (prop);
	}
	return 1;
}

Project: libx11
File: FontInfo.c

char **XListFontsWithInfo(
register Display *dpy,
_Xconst char *pattern,  /* null-terminated */
int maxNames,
int *actualCount,	/* RETURN */
XFontStruct **info)	/* RETURN */
{
    unsigned long nbytes;
    unsigned long reply_left;	/* unused data left in reply buffer */
    register int i;
    register XFontStruct *fs;
    unsigned int size = 0;
    XFontStruct *finfo = NULL;
    char **flist = NULL;
    xListFontsWithInfoReply reply;
    register xListFontsReq *req;
    int j;

    if (strlen(pattern) >= USHRT_MAX)
        return NULL;

    LockDisplay(dpy);
    GetReq(ListFontsWithInfo, req);
    req->maxNames = maxNames;
    nbytes = req->nbytes = pattern ? (CARD16) strlen (pattern) : 0;
    req->length += (nbytes + 3) >> 2;
    _XSend (dpy, pattern, nbytes);
    /* use _XSend instead of Data, since subsequent _XReply will flush buffer */

    for (i = 0; ; i++) {
	if (!_XReply (dpy, (xReply *) &reply,
		      ((SIZEOF(xListFontsWithInfoReply) -
			SIZEOF(xGenericReply)) >> 2), xFalse)) {
	    reply.nameLength = 0; /* avoid trying to read more replies */
	    reply_left = 0;
	    goto badmem;
	}
	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;
		char ** tmp_flist;

		tmp_finfo = Xreallocarray (finfo, size, sizeof(XFontStruct));
		if (tmp_finfo)
		    finfo = tmp_finfo;
		else
		    goto badmem;

		tmp_flist = Xreallocarray (flist, size + 1, sizeof(char *));
		if (tmp_flist)
		    flist = tmp_flist;
		else
		    goto badmem;
	    }
	    else {
		if (! (finfo = Xmallocarray(size, sizeof(XFontStruct))))
		    goto clearwire;
		if (! (flist = Xmallocarray(size + 1, sizeof(char *)))) {
		    Xfree(finfo);
		    goto clearwire;
		}
	    }
	}
	fs = &finfo[i];

	fs->ext_data 		= NULL;
	fs->per_char		= NULL;
	fs->fid 		= None;
	fs->direction 		= reply.drawDirection;
	fs->min_char_or_byte2	= reply.minCharOrByte2;
	fs->max_char_or_byte2 	= reply.maxCharOrByte2;
	fs->min_byte1 		= reply.minByte1;
	fs->max_byte1 		= reply.maxByte1;
	fs->default_char	= reply.defaultChar;
	fs->all_chars_exist 	= reply.allCharsExist;
	fs->ascent 		= cvtINT16toInt (reply.fontAscent);
	fs->descent 		= cvtINT16toInt (reply.fontDescent);

	/* XXX the next two statements won't work if short isn't 16 bits */
	fs->min_bounds = * (XCharStruct *) &reply.minBounds;
	fs->max_bounds = * (XCharStruct *) &reply.maxBounds;

	fs->n_properties = reply.nFontProps;
	fs->properties = NULL;
	if (fs->n_properties > 0) {
	    /* nFontProps is a CARD16 */
	    nbytes = reply.nFontProps * SIZEOF(xFontProp);
	    if ((nbytes >> 2) <= reply_left) {
		fs->properties = Xmallocarray (reply.nFontProps,
                                               sizeof(XFontProp));
	    }
	    if (! fs->properties)
		goto badmem;
	    _XRead32 (dpy, (long *)fs->properties, nbytes);
	    reply_left -= (nbytes >> 2);
	}

	/* nameLength is a CARD8 */
	nbytes = reply.nameLength + 1;
	if (!i)
	    nbytes++; /* make first string 1 byte longer, to match XListFonts */
	flist[i] = Xmalloc (nbytes);
	if (! flist[i]) {
	    if (finfo[i].properties) Xfree(finfo[i].properties);
	    goto badmem;
	}
	if (!i) {
	    *flist[0] = 0; /* zero to distinguish from XListFonts */
	    flist[0]++;
	}
	flist[i][reply.nameLength] = '\0';
	_XReadPad (dpy, flist[i], (long) reply.nameLength);
    }
    *info = finfo;
    *actualCount = i;
    if (flist)
	flist[i] = NULL; /* required in case XFreeFontNames is called */
    UnlockDisplay(dpy);
    SyncHandle();
    return (flist);


  badmem:
    /* Free all memory allocated by this function. */
    for (j=(i-1); (j >= 0); j--) {
        if (j == 0)
            flist[j]--;         /* was incremented above */
        Xfree(flist[j]);
        if (finfo[j].properties) Xfree(finfo[j].properties);
    }
    Xfree(flist);
    Xfree(finfo);

  clearwire:
    /* Clear the wire. */
    _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;
}