diff options
author | Pierre Joye <pajoye@php.net> | 2007-03-10 12:16:19 +0000 |
---|---|---|
committer | Pierre Joye <pajoye@php.net> | 2007-03-10 12:16:19 +0000 |
commit | 37ad5f77df0ad2483e717ca32c6f4abf3b94c3c9 (patch) | |
tree | 2af29feec1c05b06ece112ca57df12a5335f484a | |
parent | 319d43f4f472532386823f5f9975fa207e52c90b (diff) | |
download | php-git-37ad5f77df0ad2483e717ca32c6f4abf3b94c3c9.tar.gz |
- CVE-2007-1001, integer overflow with invalid wbmp images
-rw-r--r-- | ext/gd/config.m4 | 2 | ||||
-rw-r--r-- | ext/gd/config.w32 | 2 | ||||
-rw-r--r-- | ext/gd/libgd/gd_security.c | 33 | ||||
-rw-r--r-- | ext/gd/libgd/gdhelpers.h | 7 | ||||
-rw-r--r-- | ext/gd/libgd/wbmp.c | 16 | ||||
-rw-r--r-- | ext/gd/tests/createfromwbmp2.phpt | 47 |
6 files changed, 105 insertions, 2 deletions
diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index 343374fb5f..31980e9bb9 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -265,7 +265,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]) diff --git a/ext/gd/config.w32 b/ext/gd/config.w32 index b026477d0e..b0286b04bc 100644 --- a/ext/gd/config.w32 +++ b/ext/gd/config.w32 @@ -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_BUNDLED=1 \ diff --git a/ext/gd/libgd/gd_security.c b/ext/gd/libgd/gd_security.c new file mode 100644 index 0000000000..a5fea34c14 --- /dev/null +++ b/ext/gd/libgd/gd_security.c @@ -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; +} diff --git a/ext/gd/libgd/gdhelpers.h b/ext/gd/libgd/gdhelpers.h index 5e7d9bee73..6c469726ec 100644 --- a/ext/gd/libgd/gdhelpers.h +++ b/ext/gd/libgd/gdhelpers.h @@ -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() diff --git a/ext/gd/libgd/wbmp.c b/ext/gd/libgd/wbmp.c index d63c684ac7..258d00fe12 100644 --- a/ext/gd/libgd/wbmp.c +++ b/ext/gd/libgd/wbmp.c @@ -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,6 +185,13 @@ readwbmp (int (*getin) (void *in), void *in, Wbmp ** return_wbmp) printf ("W: %d, H: %d\n", wbmp->width, wbmp->height); #endif + if (overflow2(sizeof (int), wbmp->width) || + overflow2(sizeof (int) * wbmp->width, wbmp->height)) + { + gdFree(wbmp); + return (-1); + } + if ((wbmp->bitmap = (int *) safe_emalloc(wbmp->width * wbmp->height, sizeof(int), 0)) == NULL) { gdFree (wbmp); diff --git a/ext/gd/tests/createfromwbmp2.phpt b/ext/gd/tests/createfromwbmp2.phpt new file mode 100644 index 0000000000..88c39b02af --- /dev/null +++ b/ext/gd/tests/createfromwbmp2.phpt @@ -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 |