Subject: bug#76121: 31.0.50; crash in uniscribe_close

From: Pip Cet <[email-masked]>
Date: Fri, 07 Feb 2025 16:30:32 +0000

"Richard Copley" <[email-masked]> writes:

> Pip Cet wrote:
>
>> My guess is if we made uniscribe_close return immediately if
>> uniscribe_font->cache is NULL, this crash might be avoided.
>
> That does seem to work. Thanks.
> Another way to ensure idempotence is to set
> 'uniscribe_font->dwrite_cache' to NULL after calling
> 'w32_dwrite_free_cached_face'. This also seems to avoid the crash.

Oh, excellent! I was about to post a patch to detect the problem (which
takes forever because building Emacs in Wine does), but if you've
already tested that case we can easily fix this :-)

diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 9986c9dc2f9..89f8615dd94 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -202,6 +202,14 @@ uniscribe_close (struct font *font)
   struct uniscribe_font_info *uniscribe_font
     = (struct uniscribe_font_info *) font;
 
+  fprintf (stderr, "uniscribe_close %p %p %p\n",
+	   font, uniscribe_font->dwrite_cache,
+	   uniscribe_font->cache);
+  if (uniscribe_font->cache == NULL)
+    {
+      fprintf (stderr, "already closed, would crash here\n");
+      return;
+    }
 #ifdef HAVE_HARFBUZZ
   w32_dwrite_free_cached_face (uniscribe_font->dwrite_cache);
   if (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver

I guess we can remove the fprintf statements (I'm not even sure those
work on Windows, but I've learned the hard way not to use other printing
functions from GC), and keep just the return...

Pip