]> granicus.if.org Git - php/commitdiff
- MFH: CVE-2007-1001, integer overflow with invalid wbmp images
authorPierre Joye <pajoye@php.net>
Sat, 10 Mar 2007 12:18:36 +0000 (12:18 +0000)
committerPierre Joye <pajoye@php.net>
Sat, 10 Mar 2007 12:18:36 +0000 (12:18 +0000)
NEWS
ext/gd/config.m4
ext/gd/config.w32
ext/gd/libgd/gd_security.c [new file with mode: 0644]
ext/gd/libgd/gdhelpers.h
ext/gd/libgd/wbmp.c
ext/gd/tests/createfromwbmp2.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 69b334a01e4b0db0f66571dd2cf2aaeec25d6fa4..3e7ab31012f585694c09338fc331d0ea8e8a0ad7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,7 @@ PHP                                                                        NEWS
 - Added tidyNode::getParent() method (John, Nuno)
 - Fixed zend_llist_remove_tail (Michael Wallner, Dmitry)
 - Fixed a thread safety issue in gd gif read code (Nuno, Roman Nemecek)
+- Fixed CVE-2007-1001, GD wbmp used with invalid image size (Pierre)
 - Fixed bug #40764, line thickness not respected for horizontal and vertical 
   lines (Pierre)
 - Fixed bug #40754 (added substr() & substr_replace() overflow checks). (Ilia)
index 35af949d01ddd61c417f5e76076258de148e76dc..aae67cbd5aa15a5b981dd30272ec74e7712c8d24 100644 (file)
@@ -298,7 +298,7 @@ if test "$PHP_GD" = "yes"; then
                  libgd/gdxpm.c libgd/gdfontt.c libgd/gdfonts.c libgd/gdfontmb.c libgd/gdfontl.c \
                  libgd/gdfontg.c libgd/gdtables.c libgd/gdft.c libgd/gdcache.c libgd/gdkanji.c \
                  libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c libgd/gd_topal.c libgd/gd_gif_in.c \
-                 libgd/xbm.c libgd/gd_gif_out.c "
+                 libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c"
 
 dnl check for fabsf and floorf which are available since C99
   AC_CHECK_FUNCS(fabsf floorf)
index cc652a2627c232c13e1b157e0c9177cd54d48668..0533d8b2b50f04cc767975514d9633b8b63855ef 100644 (file)
@@ -29,7 +29,7 @@ if (PHP_GD != "no") {
                        gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c \
                        gdft.c gd_gd2.c gd_gd.c gd_gif_in.c gd_gif_out.c gdhelpers.c gd_io.c gd_io_dp.c \
                        gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \
-                       gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c", "gd");
+                       gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c", "gd");
                AC_DEFINE('HAVE_LIBGD', 1, 'GD support');
                ADD_FLAG("CFLAGS_GD", " \
 /D HAVE_GD_DYNAMIC_CTX_EX=1 \
diff --git a/ext/gd/libgd/gd_security.c b/ext/gd/libgd/gd_security.c
new file mode 100644 (file)
index 0000000..a5fea34
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+   * gd_security.c
+   *
+   * Implements buffer overflow check routines.
+   *
+   * Written 2004, Phil Knirsch.
+   * Based on netpbm fixes by Alan Cox.
+   *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "gd.h"
+
+int overflow2(int a, int b)
+{
+       if(a < 0 || b < 0) {
+               php_gd_error("gd warning: one parameter to a memory allocation multiplication is negative, failing operation gracefully\n");
+               return 1;
+       }
+       if(b == 0)
+               return 0;
+       if(a > INT_MAX / b) {
+               php_gd_error("gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully\n");
+               return 1;
+       }
+       return 0;
+}
index 5e7d9bee73bacfb90ffbb85d4a862cbc953eff53..6c469726eced10db81d0cab8a42ffb895062fbe3 100644 (file)
@@ -21,6 +21,13 @@ extern char *gd_strtok_r(char *s, char *sep, char **state);
 #define gdPFree(ptr)           pefree(ptr, 1)
 #define gdPEstrdup(ptr)                pestrdup(ptr, 1)
 
+/* Returns nonzero if multiplying the two quantities will
+       result in integer overflow. Also returns nonzero if 
+       either quantity is negative. By Phil Knirsch based on
+       netpbm fixes by Alan Cox. */
+
+int overflow2(int a, int b);
+
 #ifdef ZTS
 #define gdMutexDeclare(x) MUTEX_T x
 #define gdMutexSetup(x) x = tsrm_mutex_alloc()
index d63c684ac792451513f6d1969e9f862685893a25..605d0b57352f345f5fb844ca866d0ec12093c0bc 100644 (file)
@@ -116,6 +116,15 @@ createwbmp (int width, int height, int color)
   if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
     return (NULL);
 
+  if (overflow2(sizeof (int), width)) {
+    gdFree(wbmp);
+    return NULL;
+  }
+  if (overflow2(sizeof (int) * width, height)) {
+    gdFree(wbmp);
+    return NULL;
+  }
+
   if ((wbmp->bitmap = (int *) safe_emalloc(sizeof(int), width * height, 0)) == NULL)
     {
       gdFree (wbmp);
@@ -176,7 +185,14 @@ readwbmp (int (*getin) (void *in), void *in, Wbmp ** return_wbmp)
   printf ("W: %d, H: %d\n", wbmp->width, wbmp->height);
 #endif
 
-  if ((wbmp->bitmap = (int *) safe_emalloc(wbmp->width * wbmp->height, sizeof(int), 0)) == NULL)
+  if (overflow2(sizeof (int), wbmp->width) ||
+    overflow2(sizeof (int) * wbmp->width, wbmp->height))
+    {
+      gdFree(wbmp);
+      return (-1);
+    }
+
+  if ((wbmp->bitmap = (int *) safe_emalloc((size_t)wbmp->width * wbmp->height, sizeof(int), 0)) == NULL)
     {
       gdFree (wbmp);
       return (-1);
diff --git a/ext/gd/tests/createfromwbmp2.phpt b/ext/gd/tests/createfromwbmp2.phpt
new file mode 100644 (file)
index 0000000..88c39b0
--- /dev/null
@@ -0,0 +1,47 @@
+--TEST--
+imagecreatefromwbmp with invalid wbmp
+--SKIPIF--
+<?php
+       if (!function_exists('imagecreatefromwbmp')) die("skip gd extension not available\n");
+?>
+--FILE--
+<?php
+$filename = dirname(__FILE__) . '/_tmp.wbmp';
+$fp = fopen($filename,"wb");
+if (!$fp) {
+       exit("Failed to create <$filename>");
+}
+
+//write header
+$c = 0;
+fputs($fp, chr($c), 1);
+fputs($fp, $c, 1);
+
+//write width = 2^32 / 4 + 1
+$c = 0x84;
+fputs($fp, chr($c), 1);
+$c = 0x80;
+fputs($fp, chr($c), 1);
+fputs($fp, chr($c), 1);
+fputs($fp, chr($c), 1);
+$c = 0x01;
+fputs($fp, chr($c), 1);
+
+/*write height = 4*/
+$c = 0x04;
+fputs($fp, chr($c), 1);
+
+/*write some data to cause overflow*/
+for ($i=0; $i<10000; $i++) {
+       fwrite($fp, chr($c), 1);
+}
+
+fclose($fp);
+$im = imagecreatefromwbmp($filename);
+unlink($filename);
+?>
+--EXPECTF--
+Warning: imagecreatefromwbmp(): gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully
+ in %s on line %d
+
+Warning: imagecreatefromwbmp(): '%s' is not a valid WBMP file in %s on line %d