diff options
author | Robin Watts <robin.watts@artifex.com> | 2014-05-26 17:34:14 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2014-05-27 00:04:30 +0100 |
commit | 0c041d7fc030a9bb25c76ad72a9a028e32a78de1 (patch) | |
tree | c07dd0c7c2b39758b3bfba1b82fc6f5f90ca7aeb | |
parent | 253a976aa4c0993c0b685deaceefb3220a0825d1 (diff) | |
download | mupdf-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.
-rw-r--r-- | source/pdf/pdf-op-run.c | 21 |
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; |