Commit message: None
CVE: CVE-2016-10164
CWE: CWE-787
Vulnerability description: Multiple integer overflows in libXpm before 3.5.12, when a program requests parsing XPM extensions on a 64-bit platform, allow remote attackers to cause a denial of service (out-of-bounds write) or execute arbitrary code via (1) the number of extensions or (2) their concatenated length in a crafted XPM file, which triggers a heap-based buffer overflow.

Project: libXpm

CreateColors(
    char		**dataptr,
    unsigned int	 *data_size,
    XpmColor		 *colors,
    unsigned int	  ncolors,
    unsigned int	  cpp)
{
    char buf[BUFSIZ];
    unsigned int a, key, l;
    char *s, *s2;
    char **defaults;

    /* can ncolors be trusted here? */
    for (a = 0; a < ncolors; a++, colors++, dataptr++) {

	defaults = (char **) colors;
	if(sizeof(buf) <= cpp)
	    return(XpmNoMemory);
	strncpy(buf, *defaults++, cpp);
	s = buf + cpp;

	if(sizeof(buf) <= (s-buf))
		return XpmNoMemory;

	for (key = 1; key <= NKEYS; key++, defaults++) {
	    if ((s2 = *defaults)) {
#ifndef VOID_SPRINTF
		s +=
#endif
		/* assume C99 compliance */
			snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
#ifdef VOID_SPRINTF
		s += strlen(s);
#endif
		/* does s point out-of-bounds? */
		if(sizeof(buf) < (s-buf))
			return XpmNoMemory;
	    }
	}
	/* what about using strdup()? */
	l = s - buf + 1;
	s = (char *) XpmMalloc(l);
	if (!s)
	    return (XpmNoMemory);
	*data_size += l;
	*dataptr = strcpy(s, buf);
    }
    return (XpmSuccess);
}

Project: libXpm

CreatePixels(
    char		**dataptr,
    unsigned int	  data_size,
    unsigned int	  width,
    unsigned int	  height,
    unsigned int	  cpp,
    unsigned int	 *pixels,
    XpmColor		 *colors)
{
    char *s;
    unsigned int x, y, h, offset;

    if(height <= 1)
    	return;

    h = height - 1;

    offset = width * cpp + 1;

    if(offset <= width || offset <= cpp)
    	return;

    /* why trust h? */
    for (y = 0; y < h; y++, dataptr++) {
	s = *dataptr;
	/* why trust width? */
	for (x = 0; x < width; x++, pixels++) {
	    if(cpp > (data_size - (s - *dataptr)))
	    	return;
	    strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */
	    s += cpp;
	}
	*s = '\0';
	if(offset > data_size)
		return;
	*(dataptr + 1) = *dataptr + offset;
    }
    /* duplicate some code to avoid a test in the loop */
    s = *dataptr;
    /* why trust width? */
    for (x = 0; x < width; x++, pixels++) {
	if(cpp > data_size - (s - *dataptr))
	    	return;
	strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */
	s += cpp;
    }
    *s = '\0';
}

Project: libXpm

XpmCreateDataFromImage(
    Display		  *display,
    char		***data_return,
    XImage		  *image,
    XImage		  *shapeimage,
    XpmAttributes	  *attributes)
{
    XpmImage xpmimage;
    XpmInfo info;
    int ErrorStatus;

    /* initialize return value */
    if (data_return)
	*data_return = NULL;

    /* create an XpmImage from the image */
    ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
					     &xpmimage, attributes);
    if (ErrorStatus != XpmSuccess)
	return (ErrorStatus);

    /* create the data from the XpmImage */
    if (attributes) {
	xpmSetInfo(&info, attributes);
	ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info);
    } else
	ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL);

    /* free the XpmImage */
    XpmFreeXpmImage(&xpmimage);

    return (ErrorStatus);
}