diff options
author | Robin Watts <robin.watts@artifex.com> | 2013-07-01 15:30:07 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-07-01 15:58:00 +0100 |
commit | 10ffbc1df88eb370a73aca6b07cc797db2690b97 (patch) | |
tree | 9443e39d278b17eb84dd14261dc65c189b40f755 /source/pdf | |
parent | 7adb94c1d814b57fd6c1696dfdc7c259191540a8 (diff) | |
download | mupdf-10ffbc1df88eb370a73aca6b07cc797db2690b97.tar.xz |
Bug 694382: Fix use-after-free due to type3 fonts.
Thanks to zeniko for spotting the problem here.
Type 3 fonts contain a reference to the resources objects required
to render the glyphs. Traditionally these have been freed when the
font is freed. Unfortunately, after recent changes, freeing a PDF
object requires the pdf_document concerned to still exist.
While in most cases the type 3 resources are not used after we have
converted the type3 glyphs to display lists, this is not always the
case. For uncachable Type 3 glyphs (such as those that do not
completely define elements in the graphics state that they use, such
as color or line width), we end up running the glyphs at interpretation
time.
[ Interpretation time = when doing a direct render on the main thread,
or when creating a display list - so also on the main thread. No
multi-threading issues with file access here. ]
The fix implemented here is for each pdf document to keep a list of
the type3 fonts it has created, and to 'decouple' them from the
document when the document is destroyed. The sole effect of this
decoupling is to remove the resources (and the PDF operator buffers)
from the font. These are only ever used during interpretation, and
no further interpretations are possible without the document being
alive anyway, so this should have no net effect on operation, other
than allowing cleanup to proceed cleanly later on.
Diffstat (limited to 'source/pdf')
-rw-r--r-- | source/pdf/pdf-type3.c | 14 | ||||
-rw-r--r-- | source/pdf/pdf-xref.c | 7 |
2 files changed, 21 insertions, 0 deletions
diff --git a/source/pdf/pdf-type3.c b/source/pdf/pdf-type3.c index d136b6f5..d4c9b31a 100644 --- a/source/pdf/pdf-type3.c +++ b/source/pdf/pdf-type3.c @@ -31,6 +31,17 @@ pdf_load_type3_font(pdf_document *doc, pdf_obj *rdb, pdf_obj *dict) fz_var(fontdesc); + /* Make a new type3 font entry in the document */ + if (doc->num_type3_fonts == doc->max_type3_fonts) + { + int new_max = doc->max_type3_fonts * 2; + + if (new_max == 0) + new_max = 4; + doc->type3_fonts = fz_resize_array(doc->ctx, doc->type3_fonts, new_max, sizeof(*doc->type3_fonts)); + doc->max_type3_fonts = new_max; + } + fz_try(ctx) { obj = pdf_dict_gets(dict, "Name"); @@ -163,6 +174,9 @@ pdf_load_type3_font(pdf_document *doc, pdf_obj *rdb, pdf_obj *dict) pdf_drop_font(ctx, fontdesc); fz_rethrow_message(ctx, "cannot load type3 font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } + + doc->type3_fonts[doc->num_type3_fonts++] = fz_keep_font(ctx, fontdesc->font); + return fontdesc; } diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c index 970a83aa..ee9f8ea1 100644 --- a/source/pdf/pdf-xref.c +++ b/source/pdf/pdf-xref.c @@ -1102,6 +1102,13 @@ pdf_close_document(pdf_document *doc) if (doc->crypt) pdf_free_crypt(ctx, doc->crypt); + for (i=0; i < doc->num_type3_fonts; i++) + { + fz_decouple_type3_font(ctx, doc->type3_fonts[i], (void *)doc); + fz_drop_font(ctx, doc->type3_fonts[i]); + } + fz_free(ctx, doc->type3_fonts); + pdf_free_ocg(ctx, doc->ocg); fz_empty_store(ctx); |