The bail: path freed a newly-realized (!found) glyph with a raw
'--refcnt; free(glyph)' instead of FreeGlyph(), skipping
FreeGlyphPicture()'s release of the glyph's per-screen Picture/Pixmap
(created earlier in the same function via CreatePicture()/CreatePixmap(),
attached via SetGlyphPicture()).
Trigger: send X_RenderAddGlyphs with >= 2 glyphs where an earlier glyph is
well-formed (gets fully realized) and a later one is malformed (e.g.
declares more bitmap bytes than present, hitting the BadLength/goto bail
above) -- the earlier glyph's Picture/Pixmap leaks every such request,
repeatable unbounded-leak DoS. No OOM needed.
Fix: call FreeGlyph() instead, for both found and !found glyphs -- it
already does the right thing for each: a bare refcnt-- for a found glyph
(matching the old behavior), and the full teardown (hash removal if
present, FreeGlyphPicture(), free the struct) for a !found one. Safe to
call on a glyph never added to the global hash yet (AddGlyph() only runs on
the success path below): the hash lookup keys off this glyph's own sha1 and
simply finds an empty slot to not remove.
Found via a fleet-directed alloc-fail/UAF sweep of Xext/, not from a live
crash report.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>