Bug 5745

Summary: Extraneous FcPatternDestroy in XftFontOpenInfo leading to segfault
Product: xorg Reporter: Gautam Iyer <gautam>
Component: Lib/XftAssignee: Jeremy Huddleston Sequoia <jeremyhu>
Status: RESOLVED INVALID QA Contact:
Severity: normal    
Priority: high CC: jeremyhu
Version: unspecified   
Hardware: All   
OS: Linux (All)   
Whiteboard: 2011BRB_Reviewed
i915 platform: i915 features:
Attachments:
Description Flags
C source that segfaults because of this bug. none

Description Gautam Iyer 2006-01-28 09:57:19 UTC
Hi All,

The following code snipped results in a segfault:

    xftfont = XftFontOpenPattern( dpy, match);
    XftFontClose( dpy, xftfont);
    xftfont = XftFontOpenPattern( dpy, match);
    XftPatternDestroy( dpy, match);

I think the reason is as follows: In line 783 of xfreetype.c (Xft-2.1.7), the
function XftFontOpenInfo frees the font pattern. This is done only if the
pattern corresponds to a font that's already opened (cached).

The user is (and should be) responsible for freeing the pattern passed to
XftFontOpenPattern (which in turn calls XftFontOpenInfo). If Xft frees this
pattern for the user, then all hell breaks lose (segfault).

Also note, that in the above code snippet, commenting out the lines that close
and reopen the font results in perfectly working code.

Thanks,

Gautam
Comment 1 Gautam Iyer 2006-01-28 10:03:39 UTC
Created attachment 4493 [details]
C source that segfaults because of this bug.
Comment 2 Jeremy Huddleston Sequoia 2011-10-02 14:35:13 UTC
Using guard malloc, I caught this:


Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000001019f6ff0
0x000000010018fae0 in FcPatternDestroy (p=0x1019f6fe0) at fcpat.c:286
286	    if (p->ref == FC_REF_CONSTANT)
(gdb) bt
#0  0x000000010018fae0 in FcPatternDestroy (p=0x1019f6fe0) at fcpat.c:286
#1  0x0000000100001a45 in main (argc=1, argv=0x7fff5fbff5c0) at test.c:82
Current language:  auto; currently minimal
(gdb) list
281	FcPatternDestroy (FcPattern *p)
282	{
283	    int		    i;
284	    FcPatternElt    *elts;
285	    
286	    if (p->ref == FC_REF_CONSTANT)
287	    {
288		FcCacheObjectDereference (p);
289		return;
290	    }

malloc_history shows:
ALLOC 0x1019f6fe0-0x1019f6fff [size=32]: thread_7fff7cf91960 |start | main | 
XftFontMatch | FcFontMatch | FcFontRenderPrepare | FcPatternCreate | 
GMmalloc_zone_malloc_internal 
----
FREE  0x1019f6fe0-0x1019f6fff [size=32]: thread_7fff7cf91960 |start | main | 
XftFontOpenPattern | XftFontOpenInfo | FcPatternDestroy | GMfree | 
GMmalloc_zone_free 

So the problem is that it's being destroyed inside XftFontOpenPattern
Comment 3 Jeremy Huddleston Sequoia 2011-10-02 14:54:51 UTC
Why are we destroying the pattern here?

    for (font = (XftFontInt *) *bucket; font; font = (XftFontInt *) 
font->hash_next)
        if (XftFontInfoEqual (&font->info, fi))
        {
            if (!font->ref++)
                --info->num_unref_fonts;
            FcPatternDestroy (pattern);
            return &font->public;
        }

It dates back to the initial import.

Removing that FcPatternDestroy seems to fix the issue, but I'm surprised this 
has lasted so long... I'll send a patch to xorg-devel.
Comment 4 Jeremy Huddleston Sequoia 2012-03-10 23:30:19 UTC
From the mailing list:
<alanc>
I'm not sure, since if it passes that point, it saves the pattern in
the newly created font's font->public.pattern and then does the
FcPatternDestroy of it in XftFontDestroy.

Perhaps we just need to document that the pattern passed to XftFontOpenInfo
becomes the exclusive property of Xft and the caller is not allowed to use
it any more?

(Though it seems XftFontOpenInfo is missing from the function list in the
Xft man page, so needs more love than that.)
</alanc>

<me>
If that's the case, then this is a terrible API.  If the function returns NULL, the caller has no information about the state of its passed pattern.  It may have been deallocated and NULL returned during 'goto bail' or it may not have been deallocated and NULL returned because of invalid paramaters (currently just info == NULL).

Since the function isn't documented, I wonder if the "fix" would be to copy pattern and write documentation to this effect.  The problem would then be a leak for those expecting it to be freed, but that is certainly preferred, IMO.  Also, the leak is easily fixed by requiring the new libXft and doing their own FcPatternDestroy.

This confusion has caused problems in external projects who expect it to not be freed.  The only non-xorg hit for XftFontOpenInfo in codesearch is actually a long comment debugging this issue and removing their FcPatternDestroy:

http://google.com/codesearch#Lbvu5g5_Qs8/mrxvt-0.5.2/src/main.c&q=XftFontOpenInfo%20lang:%5Ec$&type=cs
</me>
Comment 5 Adam Jackson 2018-06-12 19:06:42 UTC
Mass closure: This bug has been untouched for more than six years, and is not
obviously still valid. Please reopen this bug or file a new report if you continue to experience issues with current releases.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.