diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-01-26 13:36:16 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-01-26 13:36:16 +0000 |
commit | 50dbc1a356577f3df15a876f6adb716dea29bdc5 (patch) | |
tree | 22b632b4992feb9c9d5e734d999509cccebe7a49 | |
parent | 227b68bb1a6d76f4224985af1993ae17e2bf0931 (diff) | |
download | mupdf-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.
-rw-r--r-- | draw/draw_scale.c | 16 | ||||
-rw-r--r-- | draw/draw_simple_scale.c | 16 |
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)); |