[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Thu Jun 26 01:34:34 PDT 2008


 poppler/CairoOutputDev.cc |   18 +++++++++++++++---
 poppler/CairoOutputDev.h  |    4 +++-
 2 files changed, 18 insertions(+), 4 deletions(-)

New commits:
commit 5498d93e59a0b79e5add3dc6181d5e98ba689217
Author: Michael Vrable <mvrable at cs.ucsd.edu>
Date:   Fri Jun 20 21:42:34 2008 -0700

    Use a single global FT_Library in CairoOutputDev
    
    Cairo may internally keep references to the FreeType fonts loaded in
    CairoFontEngine even after poppler is done with them.  Commit 42db4890e829
    ("Do not call FT_Done_Face on a live cairo_font_face_t") introduced a fix
    for one use-after-free bug, by delaying deleting an FT_Face objects until
    cairo is done with it.
    
    That fix doesn't correct all the bugs.  An FT_Library object is created for
    each CairoOutputDev object, and deleted when the CairoOutputDev goes away.
    But the FT_Library object should not be deleted while fonts loaded using it
    are still in use.  And cairo can keep references to fonts around more or
    less indefinitely.
    
    To more fully fix the problem, we can either:
     1. Keep a count of not-yet-deleted fonts associated with each FT_Library,
        and wait to call FT_Done_FreeType until it drops to zero.
     2. Never call FT_Done_FreeType.
    
    The second option is the simplest.  To avoid leaking memory FT_Library
    objects, use a single global FT_Library instead of a per-CairoOutputDev
    copy.

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 7ae19a2..6d4267e 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -74,10 +74,23 @@ void CairoImage::setImage (cairo_surface_t *image) {
 // CairoOutputDev
 //------------------------------------------------------------------------
 
+// We cannot tie the lifetime of an FT_Library object to that of
+// CairoOutputDev, since any FT_Faces created with it may end up with a
+// reference by Cairo which can be held long after the CairoOutputDev is
+// deleted.  The simplest way to avoid problems is to never tear down the
+// FT_Library instance; to avoid leaks, just use a single global instance
+// initialized the first time it is needed.
+FT_Library CairoOutputDev::ft_lib;
+GBool CairoOutputDev::ft_lib_initialized = gFalse;
+
 CairoOutputDev::CairoOutputDev() {
   xref = NULL;
 
-  FT_Init_FreeType(&ft_lib);
+  if (!ft_lib_initialized) {
+    FT_Init_FreeType(&ft_lib);
+    ft_lib_initialized = gTrue;
+  }
+
   fontEngine = NULL;
   glyphs = NULL;
   fill_pattern = NULL;
@@ -102,8 +115,7 @@ CairoOutputDev::~CairoOutputDev() {
   if (fontEngine) {
     delete fontEngine;
   }
-  FT_Done_FreeType(ft_lib);
-  
+
   if (cairo)
     cairo_destroy (cairo);
   cairo_pattern_destroy (stroke_pattern);
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 5d2b658..fad6765 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -206,7 +206,9 @@ protected:
   
   XRef *xref;			// xref table for current document
 
-  FT_Library ft_lib;
+  static FT_Library ft_lib;
+  static GBool ft_lib_initialized;
+
   CairoFontEngine *fontEngine;
   cairo_t *cairo;
   cairo_matrix_t orig_matrix;


More information about the poppler mailing list