diff options
author | Robin Watts <robin@peeves.(none)> | 2013-11-27 03:24:43 -0800 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-11-27 11:28:38 +0000 |
commit | a290828ad27a30b894e7bc11f77b612e8cec83a8 (patch) | |
tree | a1b28a508a237c910c518cc8c15e210bc5a1b790 | |
parent | b1ed116091b790223a976eca2381da2875341e10 (diff) | |
download | mupdf-a290828ad27a30b894e7bc11f77b612e8cec83a8.tar.xz |
Bug 694116: Solve valgrind issues in draw device.
The actual issue here is that a pixmap is dropped more times than
it should be due to an error in the rendering pipeline.
The problem arises because we fail to push a clip image mask, but
still pop the mask off the stack later. This puts us off by 1 in
the stack handling.
The simplest solution to this (that will be safe no matter what
mistakes are made by the caller too) is to add some simple tests
in the draw device to ensure we do not free too early.
-rw-r--r-- | source/fitz/draw-device.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c index 9146b3e2..60735460 100644 --- a/source/fitz/draw-device.c +++ b/source/fitz/draw-device.c @@ -220,7 +220,11 @@ static void fz_knockout_end(fz_draw_device *dev) else fz_blend_pixmap(state[0].dest, state[1].dest, 255, blendmode, isolated, state[1].shape); - fz_drop_pixmap(dev->ctx, state[1].dest); + /* The following test should not be required, but just occasionally + * errors can cause the stack to get out of sync, and this saves our + * bacon. */ + if (state[0].dest != state[1].dest) + fz_drop_pixmap(dev->ctx, state[1].dest); if (state[0].shape != state[1].shape) { if (state[0].shape) @@ -1352,8 +1356,13 @@ fz_draw_pop_clip(fz_device *devp) fz_paint_pixmap_with_mask(state[0].shape, state[1].shape, state[1].mask); fz_drop_pixmap(dev->ctx, state[1].shape); } - fz_drop_pixmap(dev->ctx, state[1].mask); - fz_drop_pixmap(dev->ctx, state[1].dest); + /* The following tests should not be required, but just occasionally + * errors can cause the stack to get out of sync, and this might save + * our bacon. */ + if (state[0].mask != state[1].mask) + fz_drop_pixmap(dev->ctx, state[1].mask); + if (state[0].dest != state[1].dest) + fz_drop_pixmap(dev->ctx, state[1].dest); #ifdef DUMP_GROUP_BLENDS fz_dump_blend(dev->ctx, state[0].dest, " to get "); if (state[0].shape) @@ -1579,7 +1588,11 @@ fz_draw_end_group(fz_device *devp) else fz_blend_pixmap(state[0].dest, state[1].dest, alpha * 255, blendmode, isolated, state[1].shape); - fz_drop_pixmap(dev->ctx, state[1].dest); + /* The following test should not be required, but just occasionally + * errors can cause the stack to get out of sync, and this might save + * our bacon. */ + if (state[0].dest != state[1].dest) + fz_drop_pixmap(dev->ctx, state[1].dest); if (state[0].shape != state[1].shape) { if (state[0].shape) @@ -1940,8 +1953,13 @@ fz_draw_end_tile(fz_device *devp) /* Do nothing */ } - fz_drop_pixmap(dev->ctx, state[1].dest); - fz_drop_pixmap(dev->ctx, state[1].shape); + /* The following tests should not be required, but just occasionally + * errors can cause the stack to get out of sync, and this might save + * our bacon. */ + if (state[0].dest != state[1].dest) + fz_drop_pixmap(dev->ctx, state[1].dest); + if (state[0].shape != state[1].shape) + fz_drop_pixmap(dev->ctx, state[1].shape); #ifdef DUMP_GROUP_BLENDS fz_dump_blend(dev->ctx, state[0].dest, " to get "); if (state[0].shape) |