diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2016-09-28 19:35:45 +0800 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2016-10-12 15:36:22 +0100 |
commit | 59f74777cabca2c960411f0d3e0ae8ffd2d4aaed (patch) | |
tree | 8a4adfc2f0e73106b8972dc15078432afe8d005d /source | |
parent | ffd0a70e4d0ca24934877d40189d6881d227ccb6 (diff) | |
download | mupdf-59f74777cabca2c960411f0d3e0ae8ffd2d4aaed.tar.xz |
Bug 697151: Pacify valgrind when reading padding while unpacking tiles
If e.g. an 18 x 11 PNG image used 1 bit depth and a single component
the source data fed to fz_unpack_tile() would have padding bits at the
end of each line of whole bytes, because 18 bits is not a multiple of 8.
The optimized 1 component versions of fz_unpack_tile() for a bit depth
of 1 deliberately read the padding when doing the table lookups, knowing
that this does not matter because of the construction of the table.
Valgrind is incapable of understanding this, so we provide some extra
masking (used only in PACIFY_VALGRIND builds) that explicitly mask
off the invalid bits.
Diffstat (limited to 'source')
-rw-r--r-- | source/fitz/draw-unpack.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/source/fitz/draw-unpack.c b/source/fitz/draw-unpack.c index 35ee9b41..414e68b7 100644 --- a/source/fitz/draw-unpack.c +++ b/source/fitz/draw-unpack.c @@ -14,6 +14,25 @@ static unsigned char get1_tab_1p[256][16]; static unsigned char get1_tab_255[256][8]; static unsigned char get1_tab_255p[256][16]; +/* + Bug 697012 shows that the unpacking code can confuse valgrind due + to the use of undefined bits in the padding at the end of lines. + We unpack from bits to bytes by copying from a lookup table. + Valgrind is not capable of understanding that it doesn't matter + what the undefined bits are, as the bytes we copy that correspond + to the defined bits will always agree regardless of these + undefined bits by construction of the table. + + We therefore have a VGMASK macro that explicitly masks off these + bits in PACIFY_VALGRIND builds. +*/ +#ifdef PACIFY_VALGRIND +static const unsigned char mask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; +#define VGMASK(v,m) (v & mask[(m)]) +#else +#define VGMASK(v,m) (v) +#endif + static void init_get1_tables(void) { @@ -92,7 +111,7 @@ fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, in } x = x << 3; if (x < w) - memcpy(dp, get1_tab_1[*sp], w - x); + memcpy(dp, get1_tab_1[VGMASK(*sp, w - x)], w - x); } else if (n == 1 && depth == 1 && scale == 255 && !pad && !skip) @@ -105,7 +124,7 @@ fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, in } x = x << 3; if (x < w) - memcpy(dp, get1_tab_255[*sp], w - x); + memcpy(dp, get1_tab_255[VGMASK(*sp, w - x)], w - x); } else if (n == 1 && depth == 1 && scale == 1 && pad && !skip) @@ -118,7 +137,7 @@ fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, in } x = x << 3; if (x < w) - memcpy(dp, get1_tab_1p[*sp], (w - x) << 1); + memcpy(dp, get1_tab_1p[VGMASK(*sp, w - x)], (w - x) << 1); } else if (n == 1 && depth == 1 && scale == 255 && pad && !skip) @@ -131,7 +150,7 @@ fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, in } x = x << 3; if (x < w) - memcpy(dp, get1_tab_255p[*sp], (w - x) << 1); + memcpy(dp, get1_tab_255p[VGMASK(*sp, w - x)], (w - x) << 1); } else if (depth == 8 && !pad && !skip) |