From 634bbb61f2f1b3e0fdf830f58a7ec7e39ea5a14f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 26 Oct 2020 18:14:32 +0200 Subject: [PATCH] Avoid segfaults due to using fonts that were closed * src/composite.c (composition_gstring_cache_clear_font): New function. * src/composite.h (composition_gstring_cache_clear_font): Add prototype. * src/font.c (font_clear_cache): When we are about to close a font, remove from the gstring cache any lgstring that uses this font. (Bug#42943) --- src/composite.c | 21 +++++++++++++++++++++ src/composite.h | 2 ++ src/font.c | 5 +++++ 3 files changed, 28 insertions(+) diff --git a/src/composite.c b/src/composite.c index 90f8536b2de..66c1e86aae1 100644 --- a/src/composite.c +++ b/src/composite.c @@ -677,6 +677,27 @@ composition_gstring_from_id (ptrdiff_t id) return HASH_VALUE (h, id); } +/* Remove from the composition hash table every lgstring that + references the given FONT_OBJECT. */ +void +composition_gstring_cache_clear_font (Lisp_Object font_object) +{ + struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); + + for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) + { + Lisp_Object k = HASH_KEY (h, i); + + if (!EQ (k, Qunbound)) + { + Lisp_Object gstring = HASH_VALUE (h, i); + + if (EQ (LGSTRING_FONT (gstring), font_object)) + hash_remove_from_table (h, k); + } + } +} + DEFUN ("clear-composition-cache", Fclear_composition_cache, Sclear_composition_cache, 0, 0, 0, doc: /* Internal use only. diff --git a/src/composite.h b/src/composite.h index d39fdbaae05..bdf63fed10e 100644 --- a/src/composite.h +++ b/src/composite.h @@ -332,6 +332,8 @@ extern int composition_update_it (struct composition_it *, extern ptrdiff_t composition_adjust_point (ptrdiff_t, ptrdiff_t); extern Lisp_Object composition_gstring_lookup_cache (Lisp_Object); +extern void composition_gstring_cache_clear_font (Lisp_Object); + INLINE_HEADER_END #endif /* not EMACS_COMPOSITE_H */ diff --git a/src/font.c b/src/font.c index f7c4c816b5d..8dbf8cb8999 100644 --- a/src/font.c +++ b/src/font.c @@ -2645,6 +2645,11 @@ font_clear_cache (struct frame *f, Lisp_Object cache, if (! NILP (AREF (val, FONT_TYPE_INDEX))) { eassert (font && driver == font->driver); + /* We are going to close the font, so make + sure we don't have any lgstrings lying + around in lgstring cache that reference + the font. */ + composition_gstring_cache_clear_font (val); driver->close_font (font); } } -- 2.39.2