91f922
From 82b80dcb70a7ca8986125ff412bceddafc896842 Mon Sep 17 00:00:00 2001
91f922
From: Mike Frysinger <vapier@gentoo.org>
91f922
Date: Sat, 14 May 2016 02:13:15 -0400
91f922
Subject: [PATCH] gif: avoid out-of-bound reads of masks array #209
91f922
91f922
When given invalid inputs, we might be fed the EOF marker before it is
91f922
actually the EOF.  The gif logic assumes once it sees the EOF marker,
91f922
there won't be any more data, so it leaves the cur_bits index possibly
91f922
negative.  So when we get more data, we underflow the masks array.
91f922
91f922
Flag it so we don't try to output anything more.  The image is invalid,
91f922
so we shouldn't be truncating any valid inputs.
91f922
91f922
This fixes #209.
91f922
---
91f922
 src/gd_gif_out.c | 12 +++++++++++-
91f922
 1 file changed, 11 insertions(+), 1 deletion(-)
91f922
 
91f922
From 315dbfb0e75895e3ba84f649c491956e75f1106c Mon Sep 17 00:00:00 2001
91f922
From: "Christoph M. Becker" <cmbecker69@gmx.de>
91f922
Date: Tue, 19 Jul 2016 10:43:55 +0200
91f922
Subject: [PATCH] Add test case for issue #209
91f922
91f922
---
91f922
 tests/gif/.gitignore     |   1 +
91f922
 tests/gif/CMakeLists.txt |   1 +
91f922
 tests/gif/Makemodule.am  |   4 +++-
91f922
 tests/gif/bug00209.c     |  29 +++++++++++++++++++++++++++++
91f922
 tests/gif/bug00209.gd2   | Bin 0 -> 1050 bytes
91f922
 5 files changed, 34 insertions(+), 1 deletion(-)
91f922
 create mode 100644 tests/gif/bug00209.c
91f922
 create mode 100644 tests/gif/bug00209.gd2
91f922
91f922
diff --git a/src/gd_gif_out.c b/src/gd_gif_out.c
91f922
index 51ceb75..3099d49 100644
91f922
--- a/src/gd_gif_out.c
91f922
+++ b/src/gd_gif_out.c
91f922
@@ -1442,15 +1442,23 @@ static void compress(int init_bits, gdIOCtxPtr outfile, gdImagePtr im, GifCtx *c
91f922
  * code in turn.  When the buffer fills up empty it and start over.
91f922
  */
91f922
 
91f922
-static unsigned long masks[] = {
91f922
+static const unsigned long masks[] = {
91f922
 	0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
91f922
 	0x001F, 0x003F, 0x007F, 0x00FF,
91f922
 	0x01FF, 0x03FF, 0x07FF, 0x0FFF,
91f922
 	0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
91f922
 };
91f922
 
91f922
+/* Arbitrary value to mark output is done.  When we see EOFCode, then we don't
91f922
+ * expect to see any more data.  If we do (e.g. corrupt image inputs), cur_bits
91f922
+ * might be negative, so flag it to return early.
91f922
+ */
91f922
+#define CUR_BITS_FINISHED -1000
91f922
+
91f922
 static void output(code_int code, GifCtx *ctx)
91f922
 {
91f922
+	if (ctx->cur_bits == CUR_BITS_FINISHED)
91f922
+		return;
91f922
 	ctx->cur_accum &= masks[ctx->cur_bits];
91f922
 
91f922
 	if(ctx->cur_bits > 0) {
91f922
@@ -1492,6 +1500,8 @@ static void output(code_int code, GifCtx *ctx)
91f922
 			ctx->cur_accum >>= 8;
91f922
 			ctx->cur_bits -= 8;
91f922
 		}
91f922
+		/* Flag that it's done to prevent re-entry. */
91f922
+		ctx->cur_bits = CUR_BITS_FINISHED;
91f922
 
91f922
 		flush_char(ctx);
91f922
 	}
91f922
91f922
diff --git a/tests/gif/CMakeLists.txt b/tests/gif/CMakeLists.txt
91f922
index 92010c3..d26b1fe 100644
91f922
--- a/tests/gif/CMakeLists.txt
91f922
+++ b/tests/gif/CMakeLists.txt
91f922
@@ -7,6 +7,7 @@ LIST(APPEND TESTS_FILES
91f922
 	bug00060
91f922
 	bug00066
91f922
 	bug00181
91f922
+	bug00209
91f922
 	bug00227
91f922
 )
91f922
 
91f922
diff --git a/tests/gif/bug00209.c b/tests/gif/bug00209.c
91f922
new file mode 100644
91f922
index 0000000..6eafc32
91f922
--- /dev/null
91f922
+++ b/tests/gif/bug00209.c
91f922
@@ -0,0 +1,29 @@
91f922
+/* Test case for  <https: github.com="" libgd="" libgd="" issues="" 209="">. */
91f922
+
91f922
+#include "gd.h"
91f922
+#include "gdtest.h"
91f922
+
91f922
+int main()
91f922
+{
91f922
+    gdImagePtr im;
91f922
+    FILE *fp;
91f922
+
91f922
+    /* printf("start\n"); */
91f922
+
91f922
+    fp = gdTestFileOpen("gif/bug00209.gd2");
91f922
+    gdTestAssert(fp != NULL);
91f922
+    im = gdImageCreateFromGd2(fp);
91f922
+    gdTestAssert(im != NULL);
91f922
+    fclose(fp);
91f922
+    /* printf("loaded\n"); */
91f922
+
91f922
+    fp = gdTestTempFp();
91f922
+    gdTestAssert(fp != NULL);
91f922
+    gdImageGif(im, fp);
91f922
+    fclose(fp);
91f922
+    /* printf("saved\n"); */
91f922
+
91f922
+    gdImageDestroy(im);
91f922
+
91f922
+    return gdNumFailures();
91f922
+}