avfilter/vf_drawtext: avoid double-free of aliased FT_Glyph in glyph_enu_free
authorMichael Niedermayer <michael@niedermayer.cc>
Sun, 17 May 2026 11:49:39 +0000 (13:49 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Sun, 14 Jun 2026 02:40:58 +0000 (04:40 +0200)
For glyphs whose source is already in bitmap form (color emoji fonts such
as NotoColorEmoji.ttf), FT_Glyph_To_Bitmap(..., destroy=0) returns the
input pointer unchanged. The result is that glyph->bglyph[idx] aliases
glyph->glyph (and analogously border_bglyph[t] may alias border_glyph).
glyph_enu_free then called FT_Done_Glyph on both, double-freeing the
underlying object.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 9efca1d94634c36499ca6e9ff37bddc94a61d605)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
libavfilter/vf_drawtext.c

index 64bb81cc87d46a4402758f8b656237eb033012f4..0b795778215dd5b04b6457c60afe3430e708bc18 100644 (file)
@@ -1108,16 +1108,17 @@ static int glyph_enu_free(void *opaque, void *elem)
 {
     Glyph *glyph = elem;
 
-    FT_Done_Glyph(glyph->glyph);
-    FT_Done_Glyph(glyph->border_glyph);
     for (int t = 0; t < 16; ++t) {
-        if (glyph->bglyph[t] != NULL) {
-            FT_Done_Glyph((FT_Glyph)glyph->bglyph[t]);
-        }
-        if (glyph->border_bglyph[t] != NULL) {
-            FT_Done_Glyph((FT_Glyph)glyph->border_bglyph[t]);
-        }
-    }
+        FT_Glyph bg  = (FT_Glyph)glyph->bglyph[t];
+        FT_Glyph bbg = (FT_Glyph)glyph->border_bglyph[t];
+        if (bg && bg != glyph->glyph && bg != glyph->border_glyph)
+            FT_Done_Glyph(bg);
+        if (bbg && bbg != glyph->glyph && bbg != glyph->border_glyph)
+            FT_Done_Glyph(bbg);
+    }
+    if (glyph->border_glyph && glyph->border_glyph != glyph->glyph)
+        FT_Done_Glyph(glyph->border_glyph);
+    FT_Done_Glyph(glyph->glyph);
     av_free(elem);
     return 0;
 }