[pango: 1/2] Core text: Fix indexing into cascade list when multiple fonts are selected



commit 6b85844bc9f6dbedab6e5124039120dbc075259f
Author: Jeremy Tan <jtanx outlook com>
Date:   Mon Jun 10 20:34:58 2019 +0800

    Core text: Fix indexing into cascade list when multiple fonts are selected
    
    Bug introduced from 633fd80.
    
    With that changeset, if multiple fonts from the provided font family
    are found, they are added to the start of fontset->fonts. Space for
    the cascade list (based on the 'best'/first font) then follows.
    
    However, pango_core_text_fontset_get_font_at was not updated to
    match this change. So it still assumes that there is at most only
    one 'real' font in fonset->fonts. With this assumption, the
    indexing into fontset->cascade_list became incorrect, leading to
    an out-of-bounds access on that list, resulting in an exception
    being thrown.
    
    Track the number of fonts found in pango_core_text_fontset_new
    in real_fount_count, and use this as the offset into cascade_list.
    
    This also fixes a memory leak; when a PangoCoreTextFontSet is
    initialised, fonts and coverages are pre-initialised, but this
    was being discarded and re-set in pango_core_text_fontset_new
    without freeing the previous initialisation.

 pango/pangocoretext-fontmap.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)
---
diff --git a/pango/pangocoretext-fontmap.c b/pango/pangocoretext-fontmap.c
index b4654268..427e9a0f 100644
--- a/pango/pangocoretext-fontmap.c
+++ b/pango/pangocoretext-fontmap.c
@@ -1528,6 +1528,7 @@ struct _PangoCoreTextFontset
 
   GPtrArray *fonts;
   GPtrArray *coverages;
+  guint real_font_count;
 };
 
 struct _PangoCoreTextFontsetClass
@@ -1558,10 +1559,9 @@ pango_core_text_fontset_new (PangoCoreTextFontsetKey    *key,
   gchar **family_names;
   const gchar *family;
   gchar *name;
-  GPtrArray *fonts;
   int i;
 
-  fonts = g_ptr_array_new ();
+  fontset = g_object_new (PANGO_TYPE_CORE_TEXT_FONTSET, NULL);
   family = pango_font_description_get_family (description);
   family_names = g_strsplit (family ? family : "", ",", -1);
 
@@ -1588,7 +1588,7 @@ pango_core_text_fontset_new (PangoCoreTextFontsetKey    *key,
 
               if (font)
                 {
-                  g_ptr_array_add (fonts, font);
+                  g_ptr_array_add (fontset->fonts, font);
                   if (best_font == NULL) best_font = font;
                 }
             }
@@ -1599,17 +1599,15 @@ pango_core_text_fontset_new (PangoCoreTextFontsetKey    *key,
 
   if (!best_font)
     {
-      g_ptr_array_free (fonts, false);
+      g_object_unref (fontset);
       return NULL;
     }
 
   /* Create a font set with best font */
-  fontset = g_object_new (PANGO_TYPE_CORE_TEXT_FONTSET, NULL);
   fontset->key = pango_core_text_fontset_key_copy (key);
   fontset->orig_description = pango_font_description_copy (description);
 
-  fontset->fonts = fonts;
-  fontset->coverages = g_ptr_array_new ();
+  fontset->real_font_count = fontset->fonts->len;
 
   /* Add the cascade list for this language */
 #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8
@@ -1643,9 +1641,9 @@ pango_core_text_fontset_new (PangoCoreTextFontsetKey    *key,
   fontset->cascade_list = CTFontCopyDefaultCascadeList (pango_core_text_font_get_ctfont (best_font));
 #endif
 
-  /* length of cascade list + 1 for the "real" font at the front */
-  g_ptr_array_set_size (fontset->fonts, CFArrayGetCount (fontset->cascade_list) + fonts->len);
-  g_ptr_array_set_size (fontset->coverages, CFArrayGetCount (fontset->cascade_list) + fonts->len);
+  /* length of cascade list + real_font_count for the "real" fonts at the front */
+  g_ptr_array_set_size (fontset->fonts, CFArrayGetCount (fontset->cascade_list) + fontset->real_font_count);
+  g_ptr_array_set_size (fontset->coverages, CFArrayGetCount (fontset->cascade_list) + 
fontset->real_font_count);
 
   return fontset;
 }
@@ -1674,8 +1672,8 @@ static PangoFont *
 pango_core_text_fontset_get_font_at (PangoCoreTextFontset *ctfontset,
                                      unsigned int          i)
 {
-  /* The first font is loaded as soon as the fontset is created */
-  if (i == 0)
+  /* These fonts are loaded as soon as the fontset is created */
+  if (i < ctfontset->real_font_count)
     return g_ptr_array_index (ctfontset->fonts, i);
 
   if (i >= ctfontset->fonts->len)
@@ -1683,7 +1681,7 @@ pango_core_text_fontset_get_font_at (PangoCoreTextFontset *ctfontset,
 
   if (g_ptr_array_index (ctfontset->fonts, i) == NULL)
     {
-      CTFontDescriptorRef ctdescriptor = CFArrayGetValueAtIndex (ctfontset->cascade_list, i - 1);
+      CTFontDescriptorRef ctdescriptor = CFArrayGetValueAtIndex (ctfontset->cascade_list, i - 
ctfontset->real_font_count);
       PangoFont *font = pango_core_text_fontset_load_font (ctfontset, ctdescriptor);
       g_ptr_array_index (ctfontset->fonts, i) = font;
       g_ptr_array_index (ctfontset->coverages, i) = NULL;
@@ -1712,6 +1710,7 @@ pango_core_text_fontset_init (PangoCoreTextFontset *ctfontset)
   ctfontset->cascade_list = NULL;
   ctfontset->fonts = g_ptr_array_new ();
   ctfontset->coverages = g_ptr_array_new ();
+  ctfontset->real_font_count = 0;
 }
 
 static void
@@ -1736,7 +1735,8 @@ pango_core_text_fontset_finalize (GObject *object)
     }
   g_ptr_array_free (ctfontset->coverages, TRUE);
 
-  CFRelease (ctfontset->cascade_list);
+  if (ctfontset->cascade_list)
+    CFRelease (ctfontset->cascade_list);
 
   pango_font_description_free (ctfontset->orig_description);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]