summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2016-09-28 19:35:45 +0800
committerRobin Watts <robin.watts@artifex.com>2016-10-12 15:36:22 +0100
commit59f74777cabca2c960411f0d3e0ae8ffd2d4aaed (patch)
tree8a4adfc2f0e73106b8972dc15078432afe8d005d
parentffd0a70e4d0ca24934877d40189d6881d227ccb6 (diff)
downloadmupdf-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.
-rw-r--r--source/fitz/draw-unpack.c27
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)