diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-12-14 17:53:57 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-12-18 20:30:36 +0000 |
commit | 5e969e35932106ccea0163159f0652627115081a (patch) | |
tree | 82b785e2f24da50ec72f1d0d4138c4f176441325 /fitz/dev_null.c | |
parent | bc570f7e6d8740d6c7cef91efc464c2bd36bacb8 (diff) | |
download | mupdf-5e969e35932106ccea0163159f0652627115081a.tar.xz |
Protect against draw device stack confusion due to errors while pushing.
Whenever we have an error while pushing a gstate, we run the risk of
getting confused over how many pops we need etc.
With this commit we introduce some checking at the dev_null level that
attempts to make this behaviour consistent.
Any caller may now assume that calling an operation that pushes a clip
will always succeed. This means the only error cleanup they need to
do is to ensure that if they have pushed a clip (or begun a group, or
a mask etc) is to pop it too.
Any callee may now assume that if it throws an error during the call
to a device entrypoint that would create a group/clip/mask then no more
calls will be forthcoming until after the caller has completely finished
with that group.
This is achieved by the dev_null layer (the layer that indirects from
device calls through the device structure to the function pointers)
swallowing errors and regurgitating them later as required. A count is
kept of the number of pushes that have happened since an error
occurred during a push (including that initial one). When this count
reaches zero, the original error is regurgitated. This allows the
caller to keep the cookie correctly updated.
Diffstat (limited to 'fitz/dev_null.c')
-rw-r--r-- | fitz/dev_null.c | 211 |
1 files changed, 195 insertions, 16 deletions
diff --git a/fitz/dev_null.c b/fitz/dev_null.c index 886cebe1..ac495cef 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -8,6 +8,7 @@ fz_new_device(fz_context *ctx, void *user) dev->flags = 0; dev->user = user; dev->ctx = ctx; + dev->error_depth = 0; return dev; } @@ -25,6 +26,8 @@ void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->fill_path) dev->fill_path(dev, path, even_odd, ctm, colorspace, color, alpha); } @@ -33,6 +36,8 @@ void fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->stroke_path) dev->stroke_path(dev, path, stroke, ctm, colorspace, color, alpha); } @@ -40,21 +45,57 @@ fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix void fz_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { - if (dev->clip_path) - dev->clip_path(dev, path, rect, even_odd, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_path) + dev->clip_path(dev, path, rect, even_odd, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) { - if (dev->clip_stroke_path) - dev->clip_stroke_path(dev, path, rect, stroke, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_stroke_path) + dev->clip_stroke_path(dev, path, rect, stroke, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->fill_text) dev->fill_text(dev, text, ctm, colorspace, color, alpha); } @@ -63,6 +104,8 @@ void fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->stroke_text) dev->stroke_text(dev, text, stroke, ctm, colorspace, color, alpha); } @@ -70,20 +113,59 @@ fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix void fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { - if (dev->clip_text) - dev->clip_text(dev, text, ctm, accumulate); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + if (accumulate == 0 || accumulate == 1) + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_text) + dev->clip_text(dev, text, ctm, accumulate); + } + fz_catch(ctx) + { + if (accumulate == 2) + fz_rethrow(ctx); + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { - if (dev->clip_stroke_text) - dev->clip_stroke_text(dev, text, stroke, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_stroke_text) + dev->clip_stroke_text(dev, text, stroke, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { + if (dev->error_depth) + return; if (dev->ignore_text) dev->ignore_text(dev, text, ctm); } @@ -91,6 +173,12 @@ fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) void fz_pop_clip(fz_device *dev) { + if (dev->error_depth) + { + dev->error_depth--; + if (dev->error_depth == 0) + fz_throw(dev->ctx, "%s", dev->errmess); + } if (dev->pop_clip) dev->pop_clip(dev); } @@ -98,6 +186,8 @@ fz_pop_clip(fz_device *dev) void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) { + if (dev->error_depth) + return; if (dev->fill_shade) dev->fill_shade(dev, shade, ctm, alpha); } @@ -105,6 +195,8 @@ fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) void fz_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { + if (dev->error_depth) + return; if (dev->fill_image) dev->fill_image(dev, image, ctm, alpha); } @@ -113,6 +205,8 @@ void fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { + if (dev->error_depth) + return; if (dev->fill_image_mask) dev->fill_image_mask(dev, image, ctm, colorspace, color, alpha); } @@ -120,20 +214,59 @@ fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, void fz_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm) { - if (dev->clip_image_mask) - dev->clip_image_mask(dev, image, rect, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->clip_image_mask) + dev->clip_image_mask(dev, image, rect, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc) { - if (dev->begin_mask) - dev->begin_mask(dev, area, luminosity, colorspace, bc); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->begin_mask) + dev->begin_mask(dev, area, luminosity, colorspace, bc); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_end_mask(fz_device *dev) { + if (dev->error_depth) + { + /* Converts from mask to clip, so no change in stack depth */ + return; + } if (dev->end_mask) dev->end_mask(dev); } @@ -141,13 +274,36 @@ fz_end_mask(fz_device *dev) void fz_begin_group(fz_device *dev, fz_rect area, int isolated, int knockout, int blendmode, float alpha) { - if (dev->begin_group) - dev->begin_group(dev, area, isolated, knockout, blendmode, alpha); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->begin_group) + dev->begin_group(dev, area, isolated, knockout, blendmode, alpha); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_end_group(fz_device *dev) { + if (dev->error_depth) + { + dev->error_depth--; + if (dev->error_depth == 0) + fz_throw(dev->ctx, "%s", dev->errmess); + } if (dev->end_group) dev->end_group(dev); } @@ -155,13 +311,36 @@ fz_end_group(fz_device *dev) void fz_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) { - if (dev->begin_tile) - dev->begin_tile(dev, area, view, xstep, ystep, ctm); + fz_context *ctx = dev->ctx; + + if (dev->error_depth) + { + dev->error_depth++; + return; + } + + fz_try(ctx) + { + if (dev->begin_tile) + dev->begin_tile(dev, area, view, xstep, ystep, ctm); + } + fz_catch(ctx) + { + dev->error_depth = 1; + strcpy(dev->errmess, fz_caught(ctx)); + /* Error swallowed */ + } } void fz_end_tile(fz_device *dev) { + if (dev->error_depth) + { + dev->error_depth--; + if (dev->error_depth == 0) + fz_throw(dev->ctx, "%s", dev->errmess); + } if (dev->end_tile) dev->end_tile(dev); } |