summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-05-26 17:34:14 +0100
committerRobin Watts <robin.watts@artifex.com>2014-05-27 00:04:30 +0100
commit0c041d7fc030a9bb25c76ad72a9a028e32a78de1 (patch)
treec07dd0c7c2b39758b3bfba1b82fc6f5f90ca7aeb /source
parent253a976aa4c0993c0b685deaceefb3220a0825d1 (diff)
downloadmupdf-0c041d7fc030a9bb25c76ad72a9a028e32a78de1.tar.xz
Bug 695260: Fix error handling in do_xobject
Various functions (such as fz_begin_group) handle errors internally by use of the error_depth parameter. This means that if we call them, we MUST ensure that we call the appropriate closing function. Similarly, if we don't call them, we should NOT call the closing function. In order to ensure we do this correctly, we introduce a cleanup_state variable that says which ones we tried to call. This cures the original bug.
Diffstat (limited to 'source')
-rw-r--r--source/pdf/pdf-op-run.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c
index 3d4eb9d3..bd5f39e8 100644
--- a/source/pdf/pdf-op-run.c
+++ b/source/pdf/pdf-op-run.c
@@ -1603,11 +1603,13 @@ run_xobject(pdf_csi *csi, void *state, pdf_obj *resources, pdf_xobject *xobj, co
int gparent_save;
fz_matrix gparent_save_ctm;
pdf_run_state *pr = (pdf_run_state *)state;
+ int cleanup_state = 0;
/* Avoid infinite recursion */
if (xobj == NULL || pdf_mark_obj(xobj->me))
return;
+ fz_var(cleanup_state);
fz_var(gstate);
fz_var(oldtop);
@@ -1634,8 +1636,15 @@ run_xobject(pdf_csi *csi, void *state, pdf_obj *resources, pdf_xobject *xobj, co
{
fz_rect bbox = xobj->bbox;
fz_transform_rect(&bbox, &gstate->ctm);
+
+ /* Remember that we tried to call begin_softmask. Even
+ * if it throws an error, we must call end_softmask. */
+ cleanup_state = 1;
gstate = begin_softmask(csi, pr, &softmask);
+ /* Remember that we tried to call fz_begin_group. Even
+ * if it throws an error, we must call fz_end_group. */
+ cleanup_state = 2;
fz_begin_group(pr->dev, &bbox,
xobj->isolated, xobj->knockout, gstate->blendmode, gstate->fill.alpha);
@@ -1644,6 +1653,9 @@ run_xobject(pdf_csi *csi, void *state, pdf_obj *resources, pdf_xobject *xobj, co
gstate->fill.alpha = 1;
}
+ /* Remember that we tried to save for the clippath. Even if it
+ * throws an error, we must pop it. */
+ cleanup_state = 3;
pdf_gsave(pr); /* Save here so the clippath doesn't persist */
/* clip to the bounds */
@@ -1664,13 +1676,16 @@ run_xobject(pdf_csi *csi, void *state, pdf_obj *resources, pdf_xobject *xobj, co
}
fz_always(ctx)
{
- pdf_grestore(pr); /* Remove the clippath */
+ if (cleanup_state >= 3)
+ pdf_grestore(pr); /* Remove the clippath */
/* wrap up transparency stacks */
if (xobj->transparency)
{
- fz_end_group(pr->dev);
- end_softmask(csi, pr, &softmask);
+ if (cleanup_state >= 2)
+ fz_end_group(pr->dev);
+ if (cleanup_state >= 1)
+ end_softmask(csi, pr, &softmask);
}
pr->gstate[pr->gparent].ctm = gparent_save_ctm;