summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-01-26 13:36:16 +0000
committerRobin Watts <robin.watts@artifex.com>2012-01-26 13:36:16 +0000
commit50dbc1a356577f3df15a876f6adb716dea29bdc5 (patch)
tree22b632b4992feb9c9d5e734d999509cccebe7a49 /draw
parent227b68bb1a6d76f4224985af1993ae17e2bf0931 (diff)
downloadmupdf-50dbc1a356577f3df15a876f6adb716dea29bdc5.tar.xz
Fix possible SEGV/assert in downscaler.
On extreme downscales, the weights for each pixel can all round to zero; this results in no weights being stored at all, and causes either an exception or a SEGV. The simple fix is to ensure that the first pixel that's actually in range (and there will always be one) always has a weight of at least 1. Thanks to malc for finding the test cases that lead to this bugfix.
Diffstat (limited to 'draw')
-rw-r--r--draw/draw_scale.c16
-rw-r--r--draw/draw_simple_scale.c16
2 files changed, 22 insertions, 10 deletions
diff --git a/draw/draw_scale.c b/draw/draw_scale.c
index b2e28b7b..489a2eb9 100644
--- a/draw/draw_scale.c
+++ b/draw/draw_scale.c
@@ -347,22 +347,28 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter,
dist = -dist;
f = filter->fn(filter, dist)*F;
weight = (int)(256*f+0.5f);
- if (weight == 0)
- return;
/* Ensure i is in range */
if (i < 0)
{
i = 0;
- weight = 0;
+ return;
}
else if (i >= src_w)
{
i = src_w-1;
- weight = 0;
+ return;
}
if (weight == 0)
- return;
+ {
+ /* We add a fudge factor here to allow for extreme downscales
+ * where all the weights round to 0. Ensure that at least one
+ * (arbitrarily the first one) is non zero. */
+ if (weights->new_line && f > 0)
+ weight = 1;
+ else
+ return;
+ }
DBUG(("add_weight[%d][%d] = %d(%g) dist=%g\n",j,i,weight,f,dist));
diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c
index 2d436b54..6d0ad481 100644
--- a/draw/draw_simple_scale.c
+++ b/draw/draw_simple_scale.c
@@ -303,22 +303,28 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter,
dist = -dist;
f = filter->fn(filter, dist)*F;
weight = (int)(256*f+0.5f);
- if (weight == 0)
- return;
/* Ensure i is in range */
if (i < 0)
{
i = 0;
- weight = 0;
+ return;
}
else if (i >= src_w)
{
i = src_w-1;
- weight = 0;
+ return;
}
if (weight == 0)
- return;
+ {
+ /* We add a fudge factor here to allow for extreme downscales
+ * where all the weights round to 0. Ensure that at least one
+ * (arbitrarily the first one) is non zero. */
+ if (weights->new_line && f > 0)
+ weight = 1;
+ else
+ return;
+ }
DBUG(("add_weight[%d][%d] = %d(%g) dist=%g\n",j,i,weight,f,dist));