[PATCH] render: Fix double-free on ARGB cursor error path

Adam Jackson ajax at redhat.com
Wed Aug 20 10:48:41 PDT 2014


On Wed, 2014-08-20 at 11:48 -0500, Keith Packard wrote:
> Adam Jackson <ajax at redhat.com> writes:
> 
> > The gotos deleted by this patch are the only way to get to the bail:
> > label here.  In neither case do we need to free the cursor bits from the
> > caller; AllocARGBCursor will already do that on the failure path,
> > likewise AddResource will call the resource delete function on error.
> 
> I don't see AllocARGBCursor freeing anything in the failure paths, so I
> think we need to free source/mask. We also need to free argbits

I'm not making shit up, I promise.  AllocARGBCursor glues the source and
mask parameters into the cursor bits near the top:

int
AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
                CARD32 *argb, CursorMetricPtr cm,
                unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
                unsigned backRed, unsigned backGreen, unsigned backBlue,
                CursorPtr *ppCurs, ClientPtr client, XID cid)
{
// ...
    dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)
        bits->source = psrcbits;
    bits->mask = pmaskbits;
#ifdef ARGB_CURSOR
    bits->argb = argb;
#endif

(Note hideous indentation due to missing semicolon due to
dixInitPrivates() having one in the macro definition!)  Then the unwind
looks like:

 error:
    FreeCursorBits(bits);
    dixFiniPrivates(pCurs, PRIVATE_CURSOR);
    free(pCurs);

    return rc;

And the top of FreeCursorBits looks like:

    if (--bits->refcnt > 0)
        return;
    free(bits->source);
    free(bits->mask);
#ifdef ARGB_CURSOR
    free(bits->argb);
#endif

The way I triggered this was my RealizeCursor routine returned FALSE for
argb cursors since I hadn't implemented that path yet (see Xephyr hw
cursor patch).  The valgrind chirp in the commit message was from that,
not from AddResource failing.

- ajax



More information about the xorg-devel mailing list