Commit message: Fix more unchecked lengths

Signed-off-by: Matthieu Herrb <matthieu@herrb.eu>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
CVE: CVE-2020-14344
CWE: CWE-190
Vulnerability description: An integer overflow leading to a heap-buffer overflow was found in The X Input Method (XIM) client was implemented in libX11 before version 1.6.10. As per upstream this is security relevant when setuid programs call XIM client functions while running with elevated privileges. No such programs are shipped with Red Hat Enterprise Linux.

Project: libx11
File: imRmAttr.c

_XimGetNestedListSeparator(
    XIMResourceList	 res_list,		/* LISTofIMATTR or IMATTR */
    unsigned int	 res_num)
{
    return  _XimGetResourceListRec(res_list, res_num, XNSeparatorofNestedList);
}

Project: libx11
File: imRmAttr.c

_XimEncodeIMATTRIBUTE(
    Xim			  im,
    XIMResourceList	  res_list,
    unsigned int	  res_num,
    XIMArg		 *arg,
    XIMArg		**arg_ret,
    char		 *buf,
    int			  size,
    int			 *ret_len,
    XPointer		  top,
    unsigned long	  mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;
    CARD16		*buf_s;
    int			 len;
    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
				 + sizeof(INT16); /* sizeof value length */

    *ret_len = 0;
    for (p = arg; p->name; p++) {
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimSetInnerIMAttributes(im, top, p, mode))
		continue;
	    return p->name;
	}

	check = _XimCheckIMMode(res, mode);
	if (check == XIM_CHECK_INVALID)
	    continue;
	else if (check == XIM_CHECK_ERROR)
	    return p->name;

	if (!(_XimEncodeLocalIMAttr(res, top, p->value)))
	    return p->name;

	buf_s = (CARD16 *)buf;
	if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2], (size - min_len),
				p->value, &len, mode, (XPointer)NULL)))
	    return p->name;

	if (len == 0) {
	    continue;
	} else if (len < 0) {
	    *arg_ret = p;
	    return (char *)NULL;
	}

	buf_s[0] = res->id;			/* attribute ID */
	buf_s[1] = len;				/* value length */
	XIM_SET_PAD(&buf_s[2], len);		/* pad */
	len += min_len;

	buf += len;
	*ret_len += len;
	size -= len;
    }
    *arg_ret = (XIMArg *)NULL;
    return (char *)NULL;
}

Project: libx11
File: imRmAttr.c

_XimValueToAttribute(
    XIMResourceList	 res,
    XPointer		 buf,
    int			 buf_size,
    XPointer		 value,
    int			*len,
    unsigned long	 mode,
    XPointer		 param)
{
    int			 ret_len;

    switch (res->resource_size) {
    case XimType_SeparatorOfNestedList:
    case XimType_NEST:
	*len = 0;
	break;

    case XimType_CARD8:
	ret_len = sizeof(CARD8);
	if (buf_size < ret_len + XIM_PAD(ret_len)) {
	    *len = -1;
	    return False;
	}

	*((CARD8 *)buf) = (CARD8)(long)value;
	*len = ret_len;
	break;

    case XimType_CARD16:
	ret_len = sizeof(CARD16);
	if (buf_size < ret_len + XIM_PAD(ret_len)) {
	    *len = -1;
	    return False;
	}

	*((CARD16 *)buf) = (CARD16)(long)value;
	*len = ret_len;
	break;

    case XimType_CARD32:
    case XimType_Window:
    case XimType_XIMHotKeyState:
	ret_len = sizeof(CARD32);
	if (buf_size < ret_len + XIM_PAD(ret_len)) {
	    *len = -1;
	    return False;
	}

	*((CARD32 *)buf) = (CARD32)(long)value;
	*len = ret_len;
	break;

    case XimType_STRING8:
	if (!value) {
	    *len = 0;
	    return False;
	}

	ret_len = strlen((char *)value);
	if (buf_size < ret_len + XIM_PAD(ret_len)) {
	    *len = -1;
	    return False;
	}

	(void)memcpy((char *)buf, (char *)value, ret_len);
	*len = ret_len;
	break;

    case XimType_XRectangle:
	{
	    XRectangle	*rect = (XRectangle *)value;
	    CARD16	*buf_s = (CARD16 *)buf;

	    if (!rect) {
		*len = 0;
		return False;
	    }

	    ret_len = sizeof(INT16)		/* sizeof X */
	    	    + sizeof(INT16)		/* sizeof Y */
	            + sizeof(CARD16)		/* sizeof width */
	            + sizeof(CARD16);		/* sizeof height */
	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
		*len = -1;
		return False;
	    }

	    buf_s[0] = (CARD16)rect->x;		/* X */
	    buf_s[1] = (CARD16)rect->y;		/* Y */
	    buf_s[2] = (CARD16)rect->width;	/* width */
	    buf_s[3] = (CARD16)rect->height;	/* heght */
	    *len = ret_len;
	    break;
	}

    case XimType_XPoint:
	{
	    XPoint	*point = (XPoint *)value;
	    CARD16	*buf_s = (CARD16 *)buf;

	    if (!point) {
		*len = 0;
		return False;
	    }

	    ret_len = sizeof(INT16)		/* sizeof X */
	            + sizeof(INT16);		/* sizeof Y */
	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
		*len = -1;
		return False;
	    }

	    buf_s[0] = (CARD16)point->x;		/* X */
	    buf_s[1] = (CARD16)point->y;		/* Y */
	    *len = ret_len;
	    break;
	}

    case XimType_XFontSet:
	{
	    XFontSet	 font = (XFontSet)value;
	    Xic		 ic = (Xic)param;
	    char	*base_name = NULL;
	    int		 length = 0;
	    CARD16	*buf_s = (CARD16 *)buf;

	    if (!font) {
		*len = 0;
		return False;
	    }

	    if (mode & XIM_PREEDIT_ATTR) {
		base_name = ic->private.proto.preedit_font;
		length	  = ic->private.proto.preedit_font_length;
	    } else if (mode & XIM_STATUS_ATTR) {
		base_name = ic->private.proto.status_font;
		length	  = ic->private.proto.status_font_length;
	    }

	    if (!base_name) {
		*len = 0;
		return False;
	    }

	    ret_len = sizeof(CARD16)		/* sizeof length of Base name */
		    + length;			/* sizeof Base font name list */
	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
		*len = -1;
		return False;
	    }

	    buf_s[0] = (INT16)length;		/* length of Base font name */
	    (void)memcpy((char *)&buf_s[1], base_name, length);
						/* Base font name list */
	    *len = ret_len;
	    break;
	}

    case XimType_XIMHotKeyTriggers:
	{
	    XIMHotKeyTriggers	*hotkey = (XIMHotKeyTriggers *)value;
	    INT32		 num;
	    CARD32		*buf_l = (CARD32 *)buf;
	    register CARD32	*key = (CARD32 *)&buf_l[1];
	    register int	 i;

	    if (!hotkey) {
		*len = 0;
		return False;
	    }
	    num = (INT32)hotkey->num_hot_key;

	    ret_len = sizeof(INT32)		/* sizeof number of key list */
	           + (sizeof(CARD32)		/* sizeof keysyn */
	           +  sizeof(CARD32)		/* sizeof modifier */
	           +  sizeof(CARD32))		/* sizeof modifier_mask */
	           *  num;			/* number of key list */
	    if (buf_size < ret_len + XIM_PAD(ret_len)) {
		*len = -1;
		return False;
	    }

	    buf_l[0] = num;		/* number of key list */
	    for (i = 0; i < num; i++, key += 3) {
		key[0] = (CARD32)(hotkey->key[i].keysym);
						/* keysym */
		key[1] = (CARD32)(hotkey->key[i].modifier);
						/* modifier */
		key[2] = (CARD32)(hotkey->key[i].modifier_mask);
						/* modifier_mask */
	    }
	    *len = ret_len;
	    break;
	}

    case XimType_XIMStringConversion:
	{
	    *len = 0;
	    break;
	}

    default:
	return False;
    }
    return True;
}

Project: libx11
File: imRmAttr.c

_XimEncodeTopValue(
    Xic			 ic,
    XIMResourceList	 res,
    XIMArg		*p)
{
    if (res->xrm_name == XrmStringToQuark(XNClientWindow)) {
	ic->core.client_window = (Window)p->value;
	if (ic->core.focus_window == (Window)0)
	    ic->core.focus_window = ic->core.client_window;
	_XimRegisterFilter(ic);

    } else if (res->xrm_name == XrmStringToQuark(XNFocusWindow)) {
	if (ic->core.client_window) {
	    _XimUnregisterFilter(ic);
	    ic->core.focus_window = (Window)p->value;
	    _XimRegisterFilter(ic);
	} else /* client_window not yet */
	    ic->core.focus_window = (Window)p->value;
    }
    return True;
}

Project: libx11
File: imRmAttr.c

_XimDecodeIMATTRIBUTE(
    Xim			 im,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    CARD16		*data,
    INT16		 data_len,
    XIMArg		*arg,
    BITMASK32		 mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;
    INT16		 len;
    CARD16		*buf;
    INT16		 total;
    INT16		 min_len = sizeof(CARD16)	/* sizeof attributeID */
			 	 + sizeof(INT16);	/* sizeof length */

    for (p = arg; p->name; p++) {
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimDecodeInnerIMATTRIBUTE(im, p))
		continue;
	    return p->name;
	}

	check = _XimCheckIMMode(res, mode);
	if(check == XIM_CHECK_INVALID)
	    continue;
	else if(check == XIM_CHECK_ERROR)
	    return p->name;

	total = data_len;
	buf = data;
	while (total >= min_len) {
	    if (res->id == buf[0])
		break;

	    len = buf[1];
	    len += XIM_PAD(len) + min_len;
	    buf = (CARD16 *)((char *)buf + len);
	    total -= len;
	}
	if (total < min_len)
	    return p->name;

	if (!(_XimAttributeToValue((Xic) im->private.local.current_ic,
				   res, &buf[2], buf[1], p->value, mode)))
	    return p->name;
    }
    return (char *)NULL;
}

Project: libx11
File: imRmAttr.c

_XimCheckInnerIMAttributes(
    Xim			 im,
    XIMArg		*arg,
    unsigned long	 mode)
{
    XIMResourceList	 res;
    int			 check;

    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
			im->private.proto.im_num_inner_resources, arg->name)))
	return False;

    check = _XimCheckIMMode(res, mode);
    if(check == XIM_CHECK_INVALID)
	return True;
    else if(check == XIM_CHECK_ERROR)
	return False;

    return True;
}

Project: libx11
File: imRmAttr.c

_XimEncodeSavedPreeditValue(
    Xic			  ic,
    XIMResourceList	  res,
    XPointer		  value)
{
    int			  list_ret;
    XFontStruct		**struct_list;
    char		**name_list;
    char		 *tmp;
    int			  len;
    register int	  i;

    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
	if (!value)
	    return False;

	if (ic->private.proto.preedit_font)
	    Xfree(ic->private.proto.preedit_font);

	list_ret = XFontsOfFontSet((XFontSet)value,
						&struct_list, &name_list);
	for(i = 0, len = 0; i < list_ret; i++) {
	    len += (strlen(name_list[i]) + sizeof(char));
	}
	if(!(tmp = Xmalloc(len + 1))) {
	    ic->private.proto.preedit_font = NULL;
	    return False;
	}

	tmp[0] = '\0';
	for(i = 0; i < list_ret; i++) {
	    strcat(tmp, name_list[i]);
	    strcat(tmp, ",");
	}
	tmp[len - 1] = 0;
	ic->private.proto.preedit_font        = tmp;
	ic->private.proto.preedit_font_length = len - 1;
    }
    return True;
}

Project: libx11
File: imRmAttr.c

_XimEncodePreeditValue(
    Xic			 ic,
    XIMResourceList	 res,
    XIMArg		*p)
{
    if (res->xrm_name == XrmStringToQuark(XNStdColormap)) {
	XStandardColormap	*colormap_ret;
	int			 count;

	if (!(XGetRGBColormaps(ic->core.im->core.display,
				ic->core.focus_window, &colormap_ret,
				&count, (Atom)p->value)))
	    return False;

	XFree(colormap_ret);
    } else if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
	int		  list_ret;
	XFontStruct	**struct_list;
	char		**name_list;
	char		 *tmp;
	int		  len;
	register int	  i;

	if (!p->value)
	    return False;

	Xfree(ic->private.proto.preedit_font);

	list_ret = XFontsOfFontSet((XFontSet)p->value,
						 &struct_list, &name_list);
	for (i = 0, len = 0; i < list_ret; i++) {
	     len += (strlen(name_list[i]) + sizeof(char));
	}
	if (!(tmp = Xmalloc(len + 1))) {
	    ic->private.proto.preedit_font = NULL;
	    return False;
	}

	tmp[0] = '\0';
	for (i = 0; i < list_ret; i++) {
	    strcat(tmp, name_list[i]);
	    strcat(tmp, ",");
	}
	tmp[len - 1] = 0;
	ic->private.proto.preedit_font        = tmp;
	ic->private.proto.preedit_font_length = len - 1;
    }
    return True;
}

Project: libx11
File: imRmAttr.c

_XimSetInnerICAttributes(
    Xic			 ic,
    XPointer		 top,
    XIMArg		*arg,
    unsigned long	 mode)
{
    XIMResourceList	 res;
    int			 check;

    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
			ic->private.proto.ic_num_inner_resources, arg->name)))
	return False;

    check = _XimCheckICMode(res, mode);
    if(check == XIM_CHECK_INVALID)
	return True;
    else if(check == XIM_CHECK_ERROR)
	return False;

    return _XimEncodeLocalICAttr(ic, res, top, arg, mode);
}

Project: libx11
File: imRmAttr.c

_XimDecodeICATTRIBUTE(
    Xic			 ic,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    CARD16		*data,
    INT16		 data_len,
    XIMArg		*arg,
    BITMASK32		 mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;
    INT16		 len;
    CARD16		*buf;
    INT16		 total;
    char		*name;
    INT16		 min_len = sizeof(CARD16)	/* sizeof attributeID */
			 	 + sizeof(INT16);	/* sizeof length */
    XrmQuark		 pre_quark;
    XrmQuark		 sts_quark;

    if (!arg)
	return (char *)NULL;

    pre_quark = XrmStringToQuark(XNPreeditAttributes);
    sts_quark = XrmStringToQuark(XNStatusAttributes);

    for (p = arg; p->name; p++) {
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimDecodeInnerICATTRIBUTE(ic, p, mode))
		continue;
	    return p->name;
	}

	check = _XimCheckICMode(res, mode);
	if (check == XIM_CHECK_INVALID)
	    continue;
	else if (check == XIM_CHECK_ERROR)
	    return p->name;

	total = data_len;
	buf = data;
	while (total >= min_len) {
	    if (res->id == buf[0])
		break;

	    len = buf[1];
	    len += XIM_PAD(len) + min_len;
	    buf = (CARD16 *)((char *)buf + len);
	    total -= len;
	}
	if (total < min_len)
	    return p->name;

	if (res->resource_size == XimType_NEST) {
	    if (res->xrm_name == pre_quark) {
	        if ((name = _XimDecodeICATTRIBUTE(ic, res_list, res_num,
			&buf[2], buf[1], (XIMArg *)p->value,
			(mode | XIM_PREEDIT_ATTR))))
		    return name;
	    } else if (res->xrm_name == sts_quark) {
	        if ((name = _XimDecodeICATTRIBUTE(ic, res_list, res_num,
			&buf[2], buf[1], (XIMArg *)p->value,
			(mode | XIM_STATUS_ATTR))))
		    return name;
	    }
	} else {
	    if (!(_XimAttributeToValue(ic, res, &buf[2], buf[1],
							p->value, mode)))
		return p->name;
	}
    }
    return (char *)NULL;
}

Project: libx11
File: imRmAttr.c

_XimEncodeSavedStatusValue(
    Xic			  ic,
    XIMResourceList	  res,
    XPointer		  value)
{
    int			  list_ret;
    XFontStruct		**struct_list;
    char		**name_list;
    char		 *tmp;
    int			  len;
    register int	  i;

    if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
	if (!value)
	    return False;

	Xfree(ic->private.proto.status_font);

	list_ret = XFontsOfFontSet((XFontSet)value,
						&struct_list, &name_list);
	for(i = 0, len = 0; i < list_ret; i++) {
	    len += (strlen(name_list[i]) + sizeof(char));
	}
	if(!(tmp = Xmalloc(len + 1))) {
	    ic->private.proto.status_font = NULL;
	    return False;
	}

	tmp[0] = '\0';
	for(i = 0; i < list_ret; i++) {
	    strcat(tmp, name_list[i]);
	    strcat(tmp, ",");
	}
	tmp[len - 1] = 0;
	ic->private.proto.status_font        = tmp;
	ic->private.proto.status_font_length = len - 1;
    }
    return True;
}

Project: libx11
File: imRmAttr.c

_XimSetInnerIMAttributes(
    Xim			 im,
    XPointer		 top,
    XIMArg		*arg,
    unsigned long	 mode)
{
    XIMResourceList	 res;
    int			 check;

    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
			im->private.proto.im_num_inner_resources, arg->name)))
	return False;

    check = _XimCheckIMMode(res, mode);
    if(check == XIM_CHECK_INVALID)
	return True;
    else if(check == XIM_CHECK_ERROR)
	return False;

    return _XimEncodeLocalIMAttr(res, top, arg->value);
}

Project: libx11
File: imRmAttr.c

_XimEncodeSavedIMATTRIBUTE(
    Xim			 im,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    int			*idx,
    char		*buf,
    int			 size,
    int			*ret_len,
    XPointer		 top,
    unsigned long	 mode)
{
    register int	 i;
    int			 num = im->private.proto.num_saved_imvalues;
    XrmQuark		*quark_list = im->private.proto.saved_imvalues;
    XIMResourceList	 res;
    XPointer		 value;
    CARD16		*buf_s;
    int			 len;
    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
				 + sizeof(INT16); /* sizeof value length */

    if (!im->private.proto.saved_imvalues) {
	*idx = -1;
	*ret_len = 0;
	return True;
    }

    *ret_len = 0;
    for (i = *idx; i < num; i++) {
	if (!(res = _XimGetResourceListRecByQuark(res_list,
						res_num, quark_list[i])))
	    continue;

	if (!_XimDecodeLocalIMAttr(res, top, value))
	    return False;

	buf_s = (CARD16 *)buf;
	if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
			(size - min_len), value, &len, mode, (XPointer)NULL)))
	    return False;

	if (len == 0) {
	    continue;
	} else if (len < 0) {
	    *idx = i;
	    return True;
	}

	buf_s[0] = res->id;			/* attribute ID */
	buf_s[1] = len;				/* value length */
	XIM_SET_PAD(&buf_s[2], len);		/* pad */
	len += min_len;

	buf += len;
	*ret_len += len;
	size -= len;
    }
    *idx = -1;
    return True;
}

Project: libx11
File: imRmAttr.c

_XimEncodeICATTRIBUTE(
    Xic			  ic,
    XIMResourceList	  res_list,
    unsigned int	  res_num,
    XIMArg		 *arg,
    XIMArg		**arg_ret,
    char		 *buf,
    int			  size,
    int			 *ret_len,
    XPointer		  top,
    BITMASK32		 *flag,
    unsigned long	  mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;
    CARD16		*buf_s;
    int			 len;
    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
				 + sizeof(INT16); /* sizeof value length */
    XrmQuark		 pre_quark;
    XrmQuark		 sts_quark;
    char		*name;

    pre_quark = XrmStringToQuark(XNPreeditAttributes);
    sts_quark = XrmStringToQuark(XNStatusAttributes);

    *ret_len = 0;
    for (p = arg; p && p->name; p++) {
	buf_s = (CARD16 *)buf;
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimSetInnerICAttributes(ic, top, p, mode))
		continue;
	    return p->name;
	}

	check = _XimCheckICMode(res, mode);
	if (check == XIM_CHECK_INVALID)
	    continue;
	else if (check == XIM_CHECK_ERROR)
	    return p->name;

	if (mode & XIM_PREEDIT_ATTR) {
	    if (!(_XimEncodePreeditValue(ic, res, p)))
		return p->name;
	} else if (mode & XIM_STATUS_ATTR) {
	    if (!(_XimEncodeStatusValue(ic, res, p)))
		return p->name;
	} else {
	    if (!(_XimEncodeTopValue(ic, res, p)))
		return p->name;
	}

	if (res->resource_size == XimType_NEST) {
	    XimDefICValues	*ic_attr = (XimDefICValues *)top;

	    if (res->xrm_name == pre_quark) {
		XIMArg		*arg_rt;
		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
				(XIMArg *)p->value, &arg_rt,
				(char *)&buf_s[2], (size - min_len),
				 &len, (XPointer)&ic_attr->preedit_attr, flag,
				(mode | XIM_PREEDIT_ATTR)))) {
		    return name;
		}

	    } else if (res->xrm_name == sts_quark) {
		XIMArg		*arg_rt;
		if ((name = _XimEncodeICATTRIBUTE(ic, res_list, res_num,
				(XIMArg *)p->value,  &arg_rt,
				(char *)&buf_s[2], (size - min_len),
				 &len, (XPointer)&ic_attr->status_attr, flag,
				(mode | XIM_STATUS_ATTR)))) {
		    return name;
		}
	    }
	} else {
#ifdef EXT_MOVE
	    if (flag)
		*flag |= _XimExtenArgCheck(p);
#endif
    	    if (!(_XimEncodeLocalICAttr(ic, res, top, p, mode)))
		return p->name;

	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
			 	(size - min_len), p->value,
				&len, mode, (XPointer)ic)))
		return p->name;
	}

	if (len == 0) {
	    continue;
	} else if (len < 0) {
	    *arg_ret = p;
	    return (char *)NULL;
	}

	buf_s[0] = res->id;			/* attribute ID */
	buf_s[1] = len;				/* value length */
	XIM_SET_PAD(&buf_s[2], len);		/* pad */
	len += min_len;

	buf += len;
	*ret_len += len;
	size -= len;
    }
    *arg_ret = (XIMArg *)NULL;
    return (char *)NULL;
}

Project: libx11
File: imRmAttr.c

_XimGetAttributeID(
    Xim			  im,
    CARD16		 *buf)
{
    unsigned int	  n, names_len, values_len;
    XIMResourceList	  res;
    char		 *names;
    XPointer		  tmp;
    XIMValuesList	 *values_list;
    char		**values;
    register int	  i;
    CARD16		  len;
    CARD16		  min_len = sizeof(CARD16) /* sizeof attribute ID */
				  + sizeof(CARD16) /* sizeof type of value */
				  + sizeof(INT16); /* sizeof length of attr */
    /*
     * IM attribute ID
     */

    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[1], &names_len)))
	return False;

    if (!(res = Xcalloc(n, sizeof(XIMResource))))
	return False;

    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
    if (!(tmp = Xcalloc(1, values_len))) {
	Xfree(res);
	return False;
    }

    values_list = (XIMValuesList *)tmp;
    values = (char **)((char *)tmp + sizeof(XIMValuesList));
    names = (char *)((char *)values + (sizeof(char **) * n));

    values_list->count_values = n;
    values_list->supported_values = values;

    buf++;
    for (i = 0; i < n; i++) {
	len = buf[2];
	(void)memcpy(names, (char *)&buf[3], len);
	values[i] = names;
	names[len] = '\0';
	res[i].resource_name = names;
	res[i].resource_size = buf[1];
	res[i].id	     = buf[0];
	names += (len + 1);
	len += (min_len + XIM_PAD(len + 2));
	buf = (CARD16 *)((char *)buf + len);
    }
    _XIMCompileResourceList(res, n);

    Xfree(im->core.im_resources);
    Xfree(im->core.im_values_list);

    im->core.im_resources     = res;
    im->core.im_num_resources = n;
    im->core.im_values_list   = values_list;

    /*
     * IC attribute ID
     */

    if (!(n = _XimCountNumberOfAttr(buf[0], &buf[2], &names_len)))
	return False;

    if (!(res = Xcalloc(n, sizeof(XIMResource))))
	return False;

    values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
    if (!(tmp = Xcalloc(1, values_len))) {
	Xfree(res);
	return False;
    }

    values_list = (XIMValuesList *)tmp;
    values = (char **)((char *)tmp + sizeof(XIMValuesList));
    names = (char *)((char *)values + (sizeof(char **) * n));

    values_list->count_values = n;
    values_list->supported_values = values;

    buf += 2;
    for (i = 0; i < n; i++) {
	len = buf[2];
	(void)memcpy(names, (char *)&buf[3], len);
	values[i] = names;
	names[len] = '\0';
	res[i].resource_name = names;
	res[i].resource_size = buf[1];
	res[i].id	     = buf[0];
	names += (len + 1);
	len += (min_len + XIM_PAD(len + 2));
	buf = (CARD16 *)((char *)buf + len);
    }
    _XIMCompileResourceList(res, n);


    Xfree(im->core.ic_resources);
    Xfree(im->core.ic_values_list);

    im->core.ic_resources     = res;
    im->core.ic_num_resources = n;
    im->core.ic_values_list   = values_list;

    return True;
}

Project: libx11
File: imRmAttr.c

_XimMakeIMAttrIDList(
    Xim			 im,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    XIMArg		*arg,
    CARD16		*buf,
    INT16		*len,
    unsigned long	 mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;

    *len = 0;
    if (!arg)
	return (char *)NULL;

    for (p = arg; p->name; p++) {
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimCheckInnerIMAttributes(im, p, mode))
		continue;
	    return p->name;
	}

	check = _XimCheckIMMode(res, mode);
	if (check == XIM_CHECK_INVALID)
	    continue;
	else if (check == XIM_CHECK_ERROR)
	    return p->name;

	*buf = res->id;
	*len += sizeof(CARD16);
	 buf++;
    }
    return (char *)NULL;
}

Project: libx11
File: imRmAttr.c

_XimEncodeStatusValue(
    Xic			 ic,
    XIMResourceList	 res,
    XIMArg		*p)
{
    if (res->xrm_name == XrmStringToQuark(XNStdColormap)) {
	XStandardColormap	*colormap_ret = NULL;
	int			 count;

	if (!(XGetRGBColormaps(ic->core.im->core.display,
				ic->core.focus_window, &colormap_ret,
				&count, (Atom)p->value)))
	    return False;

	XFree(colormap_ret);
    } else if (res->xrm_name == XrmStringToQuark(XNFontSet)) {
	int		  list_ret;
	XFontStruct	**struct_list;
	char		**name_list;
	char		 *tmp;
	int		  len;
	register int	  i;

	if (!p->value)
	    return False;

	Xfree(ic->private.proto.status_font);

	list_ret = XFontsOfFontSet((XFontSet)p->value,
						 &struct_list, &name_list);
	for (i = 0, len = 0; i < list_ret; i++) {
	     len += (strlen(name_list[i]) + sizeof(char));
	}
	if (!(tmp = Xmalloc(len+1))) {
	    ic->private.proto.status_font = NULL;
	    return False;
	}

	tmp[0] = '\0';
	for(i = 0; i < list_ret; i++) {
	    strcat(tmp, name_list[i]);
	    strcat(tmp, ",");
	}
	tmp[len - 1] = 0;
	ic->private.proto.status_font        = tmp;
	ic->private.proto.status_font_length = len - 1;
    }
    return True;
}

Project: libx11
File: imRmAttr.c

_XimCountNumberOfAttr(
    CARD16	  total,
    CARD16	 *attr,
    unsigned int *names_len)
{
    unsigned int n;
    CARD16	 len;
    CARD16	 min_len = sizeof(CARD16)	/* sizeof attribute ID */
			 + sizeof(CARD16)	/* sizeof type of value */
			 + sizeof(INT16);	/* sizeof length of attribute */

    n = 0;
    *names_len = 0;
    while (total > min_len) {
	len = attr[2];
	if (len >= (total - min_len)) {
	    return 0;
	}
	*names_len += (len + 1);
	len += (min_len + XIM_PAD(len + 2));
	total -= len;
	attr = (CARD16 *)((char *)attr + len);
	n++;
    }
    return n;
}

Project: libx11
File: imRmAttr.c

_XimCheckInnerICAttributes(
    Xic			 ic,
    XIMArg		*arg,
    unsigned long	 mode)
{
    XIMResourceList	 res;
    int			 check;

    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
			ic->private.proto.ic_num_inner_resources, arg->name)))
	return False;

    check = _XimCheckICMode(res, mode);
    if(check == XIM_CHECK_INVALID)
	return True;
    else if(check == XIM_CHECK_ERROR)
	return False;

    return True;
}

Project: libx11
File: imRmAttr.c

_XimEncodeSavedICATTRIBUTE(
    Xic			 ic,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    int			*idx,
    char		*buf,
    int			 size,
    int			*ret_len,
    XPointer		 top,
    unsigned long	 mode)
{
    int			 i;
    int			 num = ic->private.proto.num_saved_icvalues;
    XrmQuark		*quark_list = ic->private.proto.saved_icvalues;
    XIMResourceList	 res;
    XPointer		 value;
    CARD16		*buf_s;
    int			 len;
    int			 min_len = sizeof(CARD16) /* sizeof attribute ID */
				 + sizeof(INT16); /* sizeof value length */
    XrmQuark		 pre_quark;
    XrmQuark		 sts_quark;
    XrmQuark		 separator;

    if (!ic->private.proto.saved_icvalues) {
	*idx = -1;
	*ret_len = 0;
	return True;
    }

    pre_quark = XrmStringToQuark(XNPreeditAttributes);
    sts_quark = XrmStringToQuark(XNStatusAttributes);
    separator = XrmStringToQuark(XNSeparatorofNestedList);

    *ret_len = 0;
    for (i = *idx; i < num; i++) {
	if (quark_list[i] == separator) {
	    *idx = i;
	    return True;
	}

	if (!(res = _XimGetResourceListRecByQuark(res_list,
						res_num, quark_list[i])))
	    continue;

	if (!_XimDecodeLocalICAttr(res, top,(XPointer)&value, mode))
	    return False;

	if (mode & XIM_PREEDIT_ATTR) {
	    if (!(_XimEncodeSavedPreeditValue(ic, res, value))) {
		return False;
	    }
	} else if (mode & XIM_STATUS_ATTR) {
	    if (!(_XimEncodeSavedStatusValue(ic, res, value))) {
		return False;
	    }
	}

	buf_s = (CARD16 *)buf;
	if (res->resource_size == XimType_NEST) {
	    XimDefICValues	*ic_attr = (XimDefICValues *)top;

	    i++;
	    if (res->xrm_name == pre_quark) {
		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
				 &i, (char *)&buf_s[2], (size - min_len),
				 &len, (XPointer)&ic_attr->preedit_attr,
				(mode | XIM_PREEDIT_ATTR))) {
		    return False;
		}

	    } else if (res->xrm_name == sts_quark) {
		if (!_XimEncodeSavedICATTRIBUTE(ic, res_list, res_num,
				&i, (char *)&buf_s[2], (size - min_len),
				&len, (XPointer)&ic_attr->status_attr,
				(mode | XIM_STATUS_ATTR))) {
		    return False;
		}
	    }
	} else {
	    if (!(_XimValueToAttribute(res, (XPointer)&buf_s[2],
			 	(size - min_len), value,
				&len, mode, (XPointer)ic))) {
		return False;
	    }
	}

	if (len == 0) {
	    continue;
	} else if (len < 0) {
	    if (quark_list[i] == separator)
		i++;
	    *idx = i;
	    return True;
	}

	buf_s[0] = res->id;			/* attribute ID */
	buf_s[1] = len;				/* value length */
	XIM_SET_PAD(&buf_s[2], len);		/* pad */
	len += min_len;

	buf += len;
	*ret_len += len;
	size -= len;
    }
    *idx = -1;
    return True;
}

Project: libx11
File: imRmAttr.c

_XimDecodeInnerIMATTRIBUTE(
    Xim			 im,
    XIMArg		*arg)
{
    XIMResourceList	 res;
    XimDefIMValues	 im_values;

    if (!(res = _XimGetResourceListRec(im->private.proto.im_inner_resources,
			im->private.proto.im_num_inner_resources, arg->name)))
	return False;

    _XimGetCurrentIMValues(im, &im_values);
    return _XimDecodeLocalIMAttr(res, (XPointer)&im_values, arg->value);
}

Project: libx11
File: imRmAttr.c

_XimDecodeInnerICATTRIBUTE(
    Xic			 ic,
    XIMArg		*arg,
    unsigned long	 mode)
{
    XIMResourceList	 res;
    XimDefICValues	 ic_values;

    if (!(res = _XimGetResourceListRec(ic->private.proto.ic_inner_resources,
			ic->private.proto.ic_num_inner_resources, arg->name)))
	return False;

    _XimGetCurrentICValues(ic, &ic_values);
    if (!_XimDecodeLocalICAttr(res, (XPointer)&ic_values, arg->value, mode))
	return False;
    _XimSetCurrentICValues(ic, &ic_values);
    return True;
}

Project: libx11
File: imRmAttr.c

_XimMakeICAttrIDList(
    Xic			 ic,
    XIMResourceList	 res_list,
    unsigned int	 res_num,
    XIMArg		*arg,
    CARD16		*buf,
    INT16		*len,
    unsigned long	 mode)
{
    register XIMArg	*p;
    XIMResourceList	 res;
    int			 check;
    XrmQuark		 pre_quark;
    XrmQuark		 sts_quark;
    char		*name;
    INT16		 new_len;

    *len = 0;
    if (!arg)
	return (char *)NULL;

    pre_quark = XrmStringToQuark(XNPreeditAttributes);
    sts_quark = XrmStringToQuark(XNStatusAttributes);

    for (p = arg; p && p->name; p++) {
	if (!(res = _XimGetResourceListRec(res_list, res_num, p->name))) {
	    if (_XimCheckInnerICAttributes(ic, p, mode))
		continue;
	    *len = -1;
	    return p->name;
	}

	check = _XimCheckICMode(res, mode);
	if(check == XIM_CHECK_INVALID)
	    continue;
	else if(check == XIM_CHECK_ERROR) {
	    *len = -1;
	    return p->name;
	}

	*buf = res->id;
	*len += sizeof(CARD16);
	buf++;
	if (res->resource_size == XimType_NEST) {
	    if (res->xrm_name == pre_quark) {
		if ((name = _XimMakeICAttrIDList(ic, res_list, res_num,
				(XIMArg *)p->value, buf, &new_len,
				(mode | XIM_PREEDIT_ATTR)))) {
		    if (new_len < 0) *len = -1;
		    else *len += new_len;
		    return name;
		}
		*len += new_len;
		buf = (CARD16 *)((char *)buf + new_len);
	    } else if (res->xrm_name == sts_quark) {
		if ((name = _XimMakeICAttrIDList(ic, res_list, res_num,
				(XIMArg *)p->value, buf, &new_len,
				(mode | XIM_STATUS_ATTR)))) {
		    if (new_len < 0) *len = -1;
		    else *len += new_len;
		    return name;
		}
		*len += new_len;
		buf = (CARD16 *)((char *)buf + new_len);
	    }

	    if (!(res = _XimGetNestedListSeparator(res_list, res_num))) {
		p++;
		if (p) {
		    *len = -1;
		    return p->name;
		}
		else {
		    return (char *)NULL;
		}
	    }
	    *buf = res->id;
	    *len += sizeof(CARD16);
	    buf++;
	}
    }
    return (char *)NULL;
}