From a8cb8e94547d7e31441d2444e8a196415e3e4c1f Mon Sep 17 00:00:00 2001 From: magras Date: Thu, 28 Feb 2019 04:56:01 +0300 Subject: fix use after free in font caching algorithm Current font caching algorithm contains a use after free error. A font removed from `frc` might be still listed in `wx.specbuf`. It will lead to a crash inside `XftDrawGlyphFontSpec()`. Steps to reproduce: $ st -f 'Misc Tamsyn:scalable=false' $ curl https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt Of course, result depends on fonts installed on a system and fontconfig. In my case, I'm getting consistent segfaults with different fonts. I replaced a fixed array with a simple unbounded buffer with a constant growth rate. Cache starts with a capacity of 0, gets increments by 16, and never shrinks. On my machine after `cat UTF-8-demo.txt` buffer reaches a capacity of 192. During casual use capacity stays at 0. --- x.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/x.c b/x.c index 865dacc..2cd76d0 100644 --- a/x.c +++ b/x.c @@ -226,8 +226,9 @@ typedef struct { } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache frc[16]; +static Fontcache *frc = NULL; static int frclen = 0; +static int frccap = 0; static char *usedfont = NULL; static double usedfontsize = 0; static double defaultfontsize = 0; @@ -1244,12 +1245,14 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x fcpattern, &fcres); /* - * Overwrite or create the new cache entry. + * Allocate memory for the new cache entry. */ - if (frclen >= LEN(frc)) { - frclen = LEN(frc) - 1; - XftFontClose(xw.dpy, frc[frclen].font); - frc[frclen].unicodep = 0; + if (frclen >= frccap) { + frccap += 16; + if (!frc) + frc = xmalloc(frccap * sizeof(Fontcache)); + else + frc = xrealloc(frc, frccap * sizeof(Fontcache)); } frc[frclen].font = XftFontOpenPattern(xw.dpy, -- cgit v1.2.3-13-gbd6f