From 8dba67cb4f38d62a47757741ad41e3f245b4a32a Mon Sep 17 00:00:00 2001
From: Benjamin Otte <otte@redhat.com>
Date: Mon, 17 Aug 2015 18:52:47 +0200
Subject: pixops: Fix oversight for CVE-2015-4491

The n_x variable could be made large enough to overflow, too.

Also included are various testcases for this vulnerability:
- The original exploit (adapted for the testsuite)
- Causing overflow by making both X and Y variables large
- Causing overflow using only the X variable
- Causing overflow using only the Y variable

https://bugzilla.gnome.org/show_bug.cgi?id=752297
---
 gdk-pixbuf/pixops/pixops.c    |   6 ++-
 tests/Makefile.am             |   7 ++++
 tests/cve-2015-4491.bmp       | Bin 0 -> 82 bytes
 tests/cve-2015-4491.c         |  87 ++++++++++++++++++++++++++++++++++++++++++
 tests/resources.gresource.xml |   1 +
 5 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 tests/cve-2015-4491.bmp
 create mode 100644 tests/cve-2015-4491.c

diff --git a/gdk-pixbuf/pixops/pixops.c b/gdk-pixbuf/pixops/pixops.c
index ce51745..7f2cbff 100644
--- a/gdk-pixbuf/pixops/pixops.c
+++ b/gdk-pixbuf/pixops/pixops.c
@@ -1275,7 +1275,11 @@ make_filter_table (PixopsFilter *filter)
   gsize n_weights;
   int *weights;
 
-  n_weights = SUBSAMPLE * SUBSAMPLE * n_x * n_y;
+  n_weights = SUBSAMPLE * SUBSAMPLE * n_x;
+  if (n_weights / (SUBSAMPLE * SUBSAMPLE) != n_x)
+    return NULL; /* overflow, bail */
+
+  n_weights *= n_y;
   if (n_weights / (SUBSAMPLE * SUBSAMPLE * n_x) != n_y)
     return NULL; /* overflow, bail */
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 058ad68..42db6e2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -24,6 +24,7 @@ noinst_PROGRAMS += 			\
 
 test_programs = 			\
 	animation			\
+	cve-2015-4491			\
 	pixbuf-icon-serialize 		\
 	pixbuf-randomly-modified	\
 	pixbuf-threads			\
@@ -54,6 +55,12 @@ dist_installed_test_data =		\
 	bug725582-testrotate.png	\
 	$(wildcard $(srcdir)/test-images/*)
 
+cve_2015_4491_SOURCES =			\
+	cve-2015-4491.c			\
+	resources.h			\
+	resources.c			\
+	$(NULL)
+
 pixbuf_icc_SOURCES = 			\
 	pixbuf-icc.c			\
 	test-common.c			\
diff --git a/tests/cve-2015-4491.bmp b/tests/cve-2015-4491.bmp
new file mode 100644
index 0000000..5d3c105
Binary files /dev/null and b/tests/cve-2015-4491.bmp differ
diff --git a/tests/cve-2015-4491.c b/tests/cve-2015-4491.c
new file mode 100644
index 0000000..34ba94f
--- /dev/null
+++ b/tests/cve-2015-4491.c
@@ -0,0 +1,87 @@
+/* GdkPixbuf library - test compositing
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Otte
+ */
+
+#include <gdk-pixbuf.h>
+
+static void
+test_original (void)
+{
+  GdkPixbuf* buf;
+  int size = 32;
+  GError* err = NULL;
+
+  buf = gdk_pixbuf_new_from_resource_at_scale ("/test/resource/cve-2015-4491.bmp", size, size, FALSE, &err);
+
+  g_assert_no_error (err);
+
+  g_object_unref (buf);
+}
+
+static void
+test_scale_overflow (void)
+{
+  GdkPixbuf *src, *dest;
+
+  src = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1 << 12, 1 << 12);
+  dest = gdk_pixbuf_scale_simple (src, 1, 1, GDK_INTERP_BILINEAR);
+
+  g_object_unref (dest);
+  g_object_unref (src);
+
+}
+
+static void
+test_scalex_overflow (void)
+{
+  GdkPixbuf *src, *dest;
+
+  src = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, (((guint) G_MAXINT) + 1) >> 7, 1);
+  dest = gdk_pixbuf_scale_simple (src, 1, 1, GDK_INTERP_BILINEAR);
+
+  g_object_unref (dest);
+  g_object_unref (src);
+
+}
+
+static void
+test_scaley_overflow (void)
+{
+  GdkPixbuf *src, *dest;
+
+  src = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, (((guint) G_MAXINT) + 1) >> 7);
+  dest = gdk_pixbuf_scale_simple (src, 1, 1, GDK_INTERP_BILINEAR);
+
+  g_object_unref (dest);
+  g_object_unref (src);
+
+}
+
+int
+main (int argc, char *argv[])
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/pixbuf/cve-2015-4491/original", test_original);
+  g_test_add_func ("/pixbuf/cve-2015-4491/scale-overflow", test_scale_overflow);
+  g_test_add_func ("/pixbuf/cve-2015-4491/scale-x-overflow", test_scalex_overflow);
+  g_test_add_func ("/pixbuf/cve-2015-4491/scale-y-overflow", test_scaley_overflow);
+
+  return g_test_run ();
+}
diff --git a/tests/resources.gresource.xml b/tests/resources.gresource.xml
index 3114289..94c7b0a 100644
--- a/tests/resources.gresource.xml
+++ b/tests/resources.gresource.xml
@@ -3,6 +3,7 @@
   <gresource prefix="/test/resource">
     <file>icc-profile.png</file>
     <file preprocess="to-pixdata" alias="icc-profile.pixdata">icc-profile.png</file>
+    <file>cve-2015-4491.bmp</file>
   </gresource>
 </gresources>
  
-- 
cgit v0.11.2

