summaryrefslogtreecommitdiff
path: root/fitz/dev_null.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-12-14 17:53:57 +0000
committerRobin Watts <robin.watts@artifex.com>2012-12-18 20:30:36 +0000
commit5e969e35932106ccea0163159f0652627115081a (patch)
tree82b785e2f24da50ec72f1d0d4138c4f176441325 /fitz/dev_null.c
parentbc570f7e6d8740d6c7cef91efc464c2bd36bacb8 (diff)
downloadmupdf-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.c211
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);
}