From b0dd445c76ec8d36648c9f8c9c10b738e963908e Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Fri, 13 Jan 2012 17:58:19 +0000 Subject: Avoid infinite loops with XObjects. Every xobject keeps a reference to the object from whence it came. This is marked/unmarked as it is executed. Thanks to Zeniko for spotting the potential problem. --- pdf/mupdf.h | 1 + pdf/pdf_interpret.c | 51 +++++++++++++++++++++++++++++++-------------------- pdf/pdf_page.c | 2 +- pdf/pdf_xobject.c | 3 +++ 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/pdf/mupdf.h b/pdf/mupdf.h index 1ec9d4f2..fa7cd2f8 100644 --- a/pdf/mupdf.h +++ b/pdf/mupdf.h @@ -211,6 +211,7 @@ struct pdf_xobject_s fz_colorspace *colorspace; fz_obj *resources; fz_buffer *contents; + fz_obj *me; }; pdf_xobject *pdf_load_xobject(pdf_xref *xref, fz_obj *obj); diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c index 0cfcdfae..2cfa5d99 100644 --- a/pdf/pdf_interpret.c +++ b/pdf/pdf_interpret.c @@ -1275,24 +1275,31 @@ static void pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix transform) { fz_context *ctx = csi->dev->ctx; - pdf_gstate *gstate; + pdf_gstate *gstate = NULL; fz_matrix oldtopctm; - int oldtop; + int oldtop = 0; int popmask; - int caught = 0; - - pdf_gsave(csi); - gstate = csi->gstate + csi->gtop; - oldtop = csi->gtop; - popmask = 0; + /* Avoid infinite recursion */ + if (xobj == NULL || fz_dict_mark(xobj->me)) + return; - /* apply xobject's transform matrix */ - transform = fz_concat(xobj->matrix, transform); - gstate->ctm = fz_concat(transform, gstate->ctm); + fz_var(gstate); + fz_var(oldtop); + fz_var(popmask); fz_try(ctx) { + pdf_gsave(csi); + + gstate = csi->gstate + csi->gtop; + oldtop = csi->gtop; + popmask = 0; + + /* apply xobject's transform matrix */ + transform = fz_concat(xobj->matrix, transform); + gstate->ctm = fz_concat(transform, gstate->ctm); + /* apply soft mask, create transparency group and reset state */ if (xobj->transparency) { @@ -1343,20 +1350,24 @@ pdf_run_xobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj, fz_matrix tr pdf_run_buffer(csi, resources, xobj->contents); /* RJW: "cannot interpret XObject stream" */ } - fz_catch(ctx) + fz_always(ctx) { - caught = 1; - } - - csi->top_ctm = oldtopctm; + if (gstate) + { + csi->top_ctm = oldtopctm; - while (oldtop < csi->gtop) - pdf_grestore(csi); + while (oldtop < csi->gtop) + pdf_grestore(csi); - pdf_grestore(csi); + pdf_grestore(csi); + } - if (caught) + fz_dict_unmark(xobj->me); + } + fz_catch(ctx) + { fz_rethrow(ctx); + } /* wrap up transparency stacks */ if (xobj->transparency) diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c index 536cd5ac..7ccf78a3 100644 --- a/pdf/pdf_page.c +++ b/pdf/pdf_page.c @@ -66,7 +66,7 @@ pdf_load_page_tree_node(pdf_xref *xref, fz_obj *node, struct info info) pdf_load_page_tree_node(xref, obj, info); } } - else + else if (fz_is_dict(node)) { dict = fz_resolve_indirect(node); diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c index b56996cd..61daf9a4 100644 --- a/pdf/pdf_xobject.c +++ b/pdf/pdf_xobject.c @@ -24,6 +24,7 @@ pdf_free_xobject_imp(fz_context *ctx, fz_storable *xobj_) fz_drop_obj(xobj->resources); if (xobj->contents) fz_drop_buffer(ctx, xobj->contents); + fz_drop_obj(xobj->me); fz_free(ctx, xobj); } @@ -52,6 +53,7 @@ pdf_load_xobject(pdf_xref *xref, fz_obj *dict) form->resources = NULL; form->contents = NULL; form->colorspace = NULL; + form->me = NULL; /* Store item immediately, to avoid possible recursion if objects refer back to this one */ fz_store_item(ctx, dict, form, pdf_xobject_size(form)); @@ -104,6 +106,7 @@ pdf_load_xobject(pdf_xref *xref, fz_obj *dict) pdf_drop_xobject(ctx, form); fz_throw(ctx, "cannot load xobject content stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); } + form->me = fz_keep_obj(dict); return form; } -- cgit v1.2.3