|
1 From 0238fe2cafea2e1ed19bb222117bd73ee6898d4d Mon Sep 17 00:00:00 2001 |
|
2 From: Karl Tomlinson <karlt+@karlt.net> |
|
3 Date: Thu, 14 May 2009 10:46:29 +0000 |
|
4 Subject: [ft] Resolve mutual referencing problems with zombie faces |
|
5 |
|
6 Bug 21706 -- zombie ft_font_face / ft_unscaled_font mutual |
|
7 referencing problems |
|
8 [http://bugs.freedesktop.org/show_bug.cgi?id=21706] |
|
9 |
|
10 There can be more than one zombie font_face belonging to an unscaled_font, |
|
11 but only the first is destroyed. This leaks the client's FT_Face |
|
12 (and associated font data) as release of the FT_Face depends on release |
|
13 of the font_face. |
|
14 |
|
15 (The reason why Firefox ends up with two different font_faces for one |
|
16 unscaled_font is that load_flags for faces with artificial oblique have |
|
17 FT_LOAD_NO_BITMAP set. |
|
18 https://bugzilla.mozilla.org/show_bug.cgi?id=486974) |
|
19 |
|
20 Also it's possible for _cairo_ft_font_face_create to pull out a zombie |
|
21 font_face from the unscaled_font, which would crash |
|
22 _cairo_ft_font_face_scaled_font_create, as that expects non-null |
|
23 font_face->unscaled (if !font-face->pattern). |
|
24 --- |
|
25 diff --git a/AUTHORS b/AUTHORS |
|
26 index 289fecb..8c06174 100644 |
|
27 --- a/AUTHORS |
|
28 +++ b/AUTHORS |
|
29 @@ -86,7 +86,7 @@ Travis Spencer <tspencer@cs.pdx.edu> XCB backend fix |
|
30 Bill Spitzak <spitzak@d2.com> Build fix to find Xrender.h without xrender.pc |
|
31 Zhe Su <james.su@gmail.com> Add support for fontconfig's embeddedbitmap option |
|
32 Owen Taylor <otaylor@redhat.com> Font rewrite, documentation, win32 backend |
|
33 -Karl Tomlinson <karlt+@karlt.net> |
|
34 +Karl Tomlinson <karlt+@karlt.net> Optimisation and obscure bug fixes (mozilla) |
|
35 Alp Toker <alp@atoker.com> Fix several code/comment typos |
|
36 Malcolm Tredinnick <malcolm@commsecure.com.au> Documentation fixes |
|
37 David Turner <david@freetype.org> Optimize gradient calculations |
|
38 diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c |
|
39 index 1e2a18e..f9ff0b1 100644 |
|
40 --- a/src/cairo-ft-font.c |
|
41 +++ b/src/cairo-ft-font.c |
|
42 @@ -543,8 +543,10 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font) |
|
43 /* See comments in _ft_font_face_destroy about the "zombie" state |
|
44 * for a _ft_font_face. |
|
45 */ |
|
46 - if (unscaled->faces && !unscaled->faces->unscaled) |
|
47 + if (unscaled->faces && unscaled->faces->unscaled == NULL) { |
|
48 + assert (unscaled->faces->next == NULL); |
|
49 cairo_font_face_destroy (&unscaled->faces->base); |
|
50 + } |
|
51 } else { |
|
52 _font_map_release_face_lock_held (font_map, unscaled); |
|
53 } |
|
54 @@ -2233,9 +2235,10 @@ _cairo_ft_font_face_destroy (void *abstract_face) |
|
55 if (font_face == NULL) |
|
56 return; |
|
57 |
|
58 - /* When destroying the face created by cairo_ft_font_face_create_for_ft_face, |
|
59 + /* When destroying a face created by cairo_ft_font_face_create_for_ft_face, |
|
60 * we have a special "zombie" state for the face when the unscaled font |
|
61 - * is still alive but there are no public references to the font face. |
|
62 + * is still alive but there are no other references to a font face with |
|
63 + * the same FT_Face. |
|
64 * |
|
65 * We go from: |
|
66 * |
|
67 @@ -2249,6 +2252,8 @@ _cairo_ft_font_face_destroy (void *abstract_face) |
|
68 |
|
69 if (font_face->unscaled && |
|
70 font_face->unscaled->from_face && |
|
71 + font_face->next == NULL && |
|
72 + font_face->unscaled->faces == font_face && |
|
73 CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1) |
|
74 { |
|
75 cairo_font_face_reference (&font_face->base); |
|
76 @@ -2394,12 +2399,21 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, |
|
77 font_face->ft_options.extra_flags == ft_options->extra_flags && |
|
78 cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base)) |
|
79 { |
|
80 - if (font_face->base.status == CAIRO_STATUS_SUCCESS) |
|
81 - return cairo_font_face_reference (&font_face->base); |
|
82 + if (font_face->base.status) { |
|
83 + /* The font_face has been left in an error state, abandon it. */ |
|
84 + *prev_font_face = font_face->next; |
|
85 + break; |
|
86 + } |
|
87 |
|
88 - /* The font_face has been left in an error state, abandon it. */ |
|
89 - *prev_font_face = font_face->next; |
|
90 - break; |
|
91 + if (font_face->unscaled == NULL) { |
|
92 + /* Resurrect this "zombie" font_face (from |
|
93 + * _cairo_ft_font_face_destroy), switching its unscaled_font |
|
94 + * from owner to ownee. */ |
|
95 + font_face->unscaled = unscaled; |
|
96 + _cairo_unscaled_font_reference (&unscaled->base); |
|
97 + return &font_face->base; |
|
98 + } else |
|
99 + return cairo_font_face_reference (&font_face->base); |
|
100 } |
|
101 } |
|
102 |
|
103 @@ -2415,6 +2429,14 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, |
|
104 |
|
105 font_face->ft_options = *ft_options; |
|
106 |
|
107 + if (unscaled->faces && unscaled->faces->unscaled == NULL) { |
|
108 + /* This "zombie" font_face (from _cairo_ft_font_face_destroy) |
|
109 + * is no longer needed. */ |
|
110 + assert (unscaled->from_face && unscaled->faces->next == NULL); |
|
111 + cairo_font_face_destroy (&unscaled->faces->base); |
|
112 + unscaled->faces = NULL; |
|
113 + } |
|
114 + |
|
115 font_face->next = unscaled->faces; |
|
116 unscaled->faces = font_face; |
|
117 |
|
118 -- |
|
119 cgit v0.8.2 |