summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-12-20 16:55:25 +0000
committerRobin Watts <robin.watts@artifex.com>2012-12-21 16:26:11 +0000
commit7b3f902a25dd901515cf3b267c18bcaef4cb2297 (patch)
tree0e099df50514f0df77111e41a9f78612906999e0 /draw
parent349eeba4e75e5de284e6f29f906643b466eaa368 (diff)
downloadmupdf-7b3f902a25dd901515cf3b267c18bcaef4cb2297.tar.xz
Bug 593603: Fix problems with tiling.
Two problems with tiling are fixed here. Firstly, if the tiling bounds are huge, the 'patch' region (the region we are writing into), can overflow, causing a SEGV due to the paint code being very confused by pixmaps that go from just under INT_MAX to just over INT_MIN. Fix this by checking explicitly for overflow in these bounds. If the tiles are stupidly huge, but the scissor is small, we can end up looping many more times than we need to. We fix mapping the scissor region back through the inverse transform, and intersecting this with the pattern area. Problem found in 4201.pdf.SIGSEGV.622.3560, a test file supplied by Mateusz "j00ru" Jurczyk and Gynvael Coldwind of the Google Security Team using Address Sanitizer. Many thanks!
Diffstat (limited to 'draw')
-rw-r--r--draw/draw_device.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c
index 605a335e..2b6f62d8 100644
--- a/draw/draw_device.c
+++ b/draw/draw_device.c
@@ -1647,8 +1647,9 @@ fz_draw_end_tile(fz_device *devp)
{
fz_draw_device *dev = devp->user;
float xstep, ystep;
- fz_matrix ctm, ttm, shapectm;
- fz_rect area;
+ fz_matrix ttm, ctm, shapectm;
+ fz_rect area, scissor;
+ fz_bbox scissor_box;
int x0, y0, x1, y1, x, y;
fz_context *ctx = dev->ctx;
fz_draw_state *state;
@@ -1665,6 +1666,16 @@ fz_draw_end_tile(fz_device *devp)
area = state[1].area;
ctm = state[1].ctm;
+ /* Fudge the scissor bbox a little to allow for inaccuracies in the
+ * matrix inversion. */
+ scissor_box = fz_expand_bbox(state[0].scissor, 1);
+ scissor.x0 = (float)scissor_box.x0;
+ scissor.y0 = (float)scissor_box.y0;
+ scissor.x1 = (float)scissor_box.x1;
+ scissor.y1 = (float)scissor_box.y1;
+ scissor = fz_transform_rect(fz_invert_matrix(ctm), scissor);
+ area = fz_intersect_rect(area, scissor);
+
x0 = floorf(area.x0 / xstep);
y0 = floorf(area.y0 / ystep);
x1 = ceilf(area.x1 / xstep);
@@ -1696,6 +1707,10 @@ fz_draw_end_tile(fz_device *devp)
ttm = fz_concat(fz_translate(x * xstep, y * ystep), ctm);
state[1].dest->x = ttm.e;
state[1].dest->y = ttm.f;
+ if (state[1].dest->x > 0 && state[1].dest->x + state[1].dest->w < 0)
+ continue;
+ if (state[1].dest->y > 0 && state[1].dest->y + state[1].dest->h < 0)
+ continue;
fz_paint_pixmap_with_rect(state[0].dest, state[1].dest, 255, state[0].scissor);
if (state[1].shape)
{