summaryrefslogtreecommitdiff
path: root/src/gd_gif_out.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2016-05-14 02:13:15 -0400
committerMike Frysinger <vapier@gentoo.org>2016-05-14 02:13:15 -0400
commit82b80dcb70a7ca8986125ff412bceddafc896842 (patch)
treeb294d731bbccd8b7c07a5d1d7c33efda02f28d81 /src/gd_gif_out.c
parent4dc1a2d7931017d3625f2d7cff70a17ce58b53b4 (diff)
downloadlibgd-82b80dcb70a7ca8986125ff412bceddafc896842.tar.gz
gif: avoid out-of-bound reads of masks array #209
When given invalid inputs, we might be fed the EOF marker before it is actually the EOF. The gif logic assumes once it sees the EOF marker, there won't be any more data, so it leaves the cur_bits index possibly negative. So when we get more data, we underflow the masks array. Flag it so we don't try to output anything more. The image is invalid, so we shouldn't be truncating any valid inputs. This fixes #209.
Diffstat (limited to 'src/gd_gif_out.c')
-rw-r--r--src/gd_gif_out.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/gd_gif_out.c b/src/gd_gif_out.c
index 51ceb75..3099d49 100644
--- a/src/gd_gif_out.c
+++ b/src/gd_gif_out.c
@@ -1442,15 +1442,23 @@ nomatch:
* code in turn. When the buffer fills up empty it and start over.
*/
-static unsigned long masks[] = {
+static const unsigned long masks[] = {
0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
};
+/* Arbitrary value to mark output is done. When we see EOFCode, then we don't
+ * expect to see any more data. If we do (e.g. corrupt image inputs), cur_bits
+ * might be negative, so flag it to return early.
+ */
+#define CUR_BITS_FINISHED -1000
+
static void output(code_int code, GifCtx *ctx)
{
+ if (ctx->cur_bits == CUR_BITS_FINISHED)
+ return;
ctx->cur_accum &= masks[ctx->cur_bits];
if(ctx->cur_bits > 0) {
@@ -1492,6 +1500,8 @@ static void output(code_int code, GifCtx *ctx)
ctx->cur_accum >>= 8;
ctx->cur_bits -= 8;
}
+ /* Flag that it's done to prevent re-entry. */
+ ctx->cur_bits = CUR_BITS_FINISHED;
flush_char(ctx);
}