Commit message: None
CVE: CVE-2007-5199
CWE: CWE-119
Vulnerability description: A single byte overflow in catalogue.c in X.Org libXfont 1.3.1 allows remote attackers to have unspecified impact.

Project: libxfont

CatalogueAddFPE (CataloguePtr cat, FontPathElementPtr fpe)
{
    FontPathElementPtr *new;

    if (cat->fpeCount >= cat->fpeAlloc)
    {
	if (cat->fpeAlloc == 0)
	    cat->fpeAlloc = 16;
	else
	    cat->fpeAlloc *= 2;
	
	new = xrealloc(cat->fpeList,
		       cat->fpeAlloc * sizeof(FontPathElementPtr));
	if (new == NULL)
	    return AllocError;

	cat->fpeList = new;
    }

    cat->fpeList[cat->fpeCount++] = fpe;

    return Successful;
}

Project: libxfont

CatalogueCloseFont (FontPathElementPtr fpe, FontPtr pFont)
{
    /* Note: this gets called with the actual subfpe where we found
     * the font, not the catalogue fpe. */

    FontFileCloseFont(fpe, pFont);
}

Project: libxfont

CatalogueFreeFPE (FontPathElementPtr fpe)
{
    CataloguePtr	cat = fpe->private;

    /* If the catalogue is modified while the xserver has fonts open
     * from the previous subfpes, we'll unref the old subfpes when we
     * reload the catalogue, and the xserver will the call FreeFPE on
     * them once it drops its last reference. Thus, the FreeFPE call
     * for the subfpe ends up here and we just forward it to
     * FontFileFreeFPE. */

    if (!CatalogueNameCheck (fpe->name))
	return FontFileFreeFPE (fpe);

    CatalogueUnrefFPEs (fpe);
    xfree(cat->fpeList);
    xfree(cat);

    return Successful;
}

Project: libxfont

CatalogueInitFPE (FontPathElementPtr fpe)
{
    CataloguePtr	cat;

    cat = (CataloguePtr) xalloc(sizeof *cat);
    if (cat == NULL)
	return AllocError;

    fpe->private = (pointer) cat;
    cat->fpeCount = 0;
    cat->fpeAlloc = 0;
    cat->fpeList = NULL;
    cat->mtime = 0;

    return CatalogueRescan (fpe);
}

Project: libxfont

CatalogueListFonts (pointer client, FontPathElementPtr fpe, char *pat, 
		    int len, int max, FontNamesPtr names)
{
    CataloguePtr cat = fpe->private;
    FontPathElementPtr subfpe;
    FontDirectoryPtr dir;
    int i;

    CatalogueRescan (fpe);

    for (i = 0; i < cat->fpeCount; i++)
    {
	subfpe = cat->fpeList[i];
	dir = subfpe->private;
	FontFileListFonts(client, subfpe, pat, len, max, names);
    }

    return Successful;
}

Project: libxfont

CatalogueListNextFontOrAlias(pointer client, FontPathElementPtr fpe, 
			     char **namep, int *namelenp, char **resolvedp,
			     int *resolvedlenp, pointer private)
{
    LFWIDataPtr		data = private;
    CataloguePtr	cat = fpe->private;
    int			ret;

    if (data->current == cat->fpeCount)
    {
	xfree(data);
	return BadFontName;
    }

    ret = FontFileListNextFontOrAlias(client, cat->fpeList[data->current],
				      namep, namelenp,
				      resolvedp, resolvedlenp,
				      data->privates[data->current]);
    if (ret == BadFontName)
    {
	data->current++;
	return CatalogueListNextFontOrAlias(client, fpe, namep, namelenp,
					    resolvedp, resolvedlenp, private);
    }

    return ret;
}

Project: libxfont

CatalogueListNextFontWithInfo(pointer client, FontPathElementPtr fpe, 
			      char **namep, int *namelenp, 
			      FontInfoPtr *pFontInfo,
			      int *numFonts, pointer private)
{
    LFWIDataPtr		data = private;
    CataloguePtr	cat = fpe->private;
    int			ret;

    if (data->current == cat->fpeCount)
    {
	xfree(data);
	return BadFontName;
    }

    ret = FontFileListNextFontWithInfo(client, cat->fpeList[data->current],
				       namep, namelenp,
				       pFontInfo, numFonts,
				       data->privates[data->current]);
    if (ret == BadFontName)
    {
	data->current++;
	return CatalogueListNextFontWithInfo(client, fpe, namep, namelenp,
					     pFontInfo, numFonts, private);
    }

    return ret;
}

Project: libxfont

CatalogueNameCheck (char *name)
{
    return strncmp(name, CataloguePrefix, sizeof(CataloguePrefix) - 1) == 0;
}

Project: libxfont

CatalogueOpenFont (pointer client, FontPathElementPtr fpe, Mask flags, 
		   char *name, int namelen, 
		   fsBitmapFormat format, fsBitmapFormatMask fmask,
		   XID id, FontPtr *pFont, char **aliasName, 
		   FontPtr non_cachable_font)
{
    CataloguePtr cat = fpe->private;
    FontPathElementPtr subfpe;
    FontDirectoryPtr dir;
    int i, status;

    CatalogueRescan (fpe);

    for (i = 0; i < cat->fpeCount; i++)
    {
	subfpe = cat->fpeList[i];
	dir = subfpe->private;
	status = FontFileOpenFont(client, subfpe, flags,
				  name, namelen, format, fmask, id,
				  pFont, aliasName, non_cachable_font);
	if (status == Successful || status == FontNameAlias)
	    return status;
    }
	    
    return BadFontName;
}

Project: libxfont

CatalogueRegisterLocalFpeFunctions (void)
{
    RegisterFPEFunctions(CatalogueNameCheck,
			 CatalogueInitFPE,
			 CatalogueFreeFPE,
			 CatalogueResetFPE,
			 CatalogueOpenFont,
			 CatalogueCloseFont,
			 CatalogueListFonts,
			 CatalogueStartListFontsWithInfo,
			 CatalogueListNextFontWithInfo,
			 NULL,
			 NULL,
			 NULL,
			 CatalogueStartListFontsAndAliases,
			 CatalogueListNextFontOrAlias,
			 FontFileEmptyBitmapSource);
}

Project: libxfont

CatalogueResetFPE (FontPathElementPtr fpe)
{
    /* Always just tell the caller to close and re-open */
    return FPEResetFailed;	
}

Project: libxfont

CatalogueStartListFonts(pointer client, FontPathElementPtr fpe, 
			char *pat, int len, int max, pointer *privatep,
			int mark_aliases)
{
    CataloguePtr	cat = fpe->private;
    LFWIDataPtr		data;
    int			ret, i, j;

    CatalogueRescan (fpe);

    data = (LFWIDataPtr) xalloc (sizeof *data +
				 sizeof data->privates[0] * cat->fpeCount);
    if (!data)
	return AllocError;
    data->privates = (pointer *) (data + 1);

    for (i = 0; i < cat->fpeCount; i++)
    {
	ret = FontFileStartListFonts(client, cat->fpeList[i], pat, len,
				     max, &data->privates[i], mark_aliases);
	if (ret != Successful)
	    goto bail;
    }

    data->current = 0;
    *privatep = (pointer) data;
    return Successful;

 bail:
    for (j = 0; j < i; j++)
	/* FIXME: we have no way to free the per-fpe privates. */;
    xfree (data);

    return AllocError;
}

Project: libxfont

CatalogueStartListFontsAndAliases(pointer client, FontPathElementPtr fpe, 
				  char *pat, int len, int max, 
				  pointer *privatep)
{
    return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 1);
}

Project: libxfont

CatalogueStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, 
				char *pat, int len, int max, 
				pointer *privatep)
{
    return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 0);
}

Project: libxfont

CatalogueUnrefFPEs (FontPathElementPtr fpe)
{
    CataloguePtr	cat = fpe->private;
    FontPathElementPtr	subfpe;
    int			i;

    for (i = 0; i < cat->fpeCount; i++)
    {
	subfpe = cat->fpeList[i];
	subfpe->refcount--;
	if (subfpe->refcount == 0)
	{
	    FontFileFreeFPE (subfpe);
	    xfree(subfpe->name);
	    xfree(subfpe);
	}
    }

    cat->fpeCount = 0;
}

Project: libxfont

ComparePriority(const void *p1, const void *p2)
{
    FontDirectoryPtr dir1 = (*(FontPathElementPtr*) p1)->private;
    FontDirectoryPtr dir2 = (*(FontPathElementPtr*) p2)->private;
    const char *pri1 = NULL;
    const char *pri2 = NULL;

    if (dir1->attributes != NULL)
	pri1 = strstr(dir1->attributes, PriorityAttribute);
    if (dir2->attributes != NULL)
	pri2 = strstr(dir2->attributes, PriorityAttribute);

    if (pri1 == NULL && pri2 == NULL)
	return 0;
    else if (pri1 == NULL)
	return 1;
    else if (pri2 == NULL)
	return -1;
    else
	return
	    atoi(pri1 + strlen(PriorityAttribute)) -
	    atoi(pri2 + strlen(PriorityAttribute));
}