summaryrefslogtreecommitdiffstats
path: root/php-5.5.6-CVE-2013-7226.patch
diff options
context:
space:
mode:
Diffstat (limited to 'php-5.5.6-CVE-2013-7226.patch')
-rw-r--r--php-5.5.6-CVE-2013-7226.patch515
1 files changed, 515 insertions, 0 deletions
diff --git a/php-5.5.6-CVE-2013-7226.patch b/php-5.5.6-CVE-2013-7226.patch
new file mode 100644
index 0000000..4dc8302
--- /dev/null
+++ b/php-5.5.6-CVE-2013-7226.patch
@@ -0,0 +1,515 @@
+From 2938329ce19cb8c4197dec146c3ec887c6f61d01 Mon Sep 17 00:00:00 2001
+From: Xinchen Hui <laruence@php.net>
+Date: Fri, 27 Dec 2013 14:04:59 +0800
+Subject: [PATCH] Fixed bug #66356 (Heap Overflow Vulnerability in imagecrop())
+
+And also fixed the bug: arguments are altered after some calls
+---
+ NEWS | 1 +
+ ext/gd/gd.c | 181 ++++++++++++++++++++++++++++++++++++---------
+ ext/gd/tests/bug66356.phpt | 22 ++++++
+ main/php_version.h | 6 +-
+ 4 files changed, 173 insertions(+), 37 deletions(-)
+ create mode 100644 ext/gd/tests/bug66356.phpt
+
+diff --git a/ext/gd/gd.c b/ext/gd/gd.c
+index fb25821..49970c1 100644
+--- a/ext/gd/gd.c
++++ b/ext/gd/gd.c
+@@ -1538,9 +1538,15 @@ PHP_FUNCTION(imagesetstyle)
+ break;
+ }
+
+- convert_to_long_ex(item);
+-
+- stylearr[index++] = Z_LVAL_PP(item);
++ if (Z_TYPE_PP(item) != IS_LONG) {
++ zval lval;
++ lval = **item;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ stylearr[index++] = Z_LVAL(lval);
++ } else {
++ stylearr[index++] = Z_LVAL_PP(item);
++ }
+ }
+
+ gdImageSetStyle(im, stylearr, index);
+@@ -3346,14 +3352,26 @@ static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled)
+
+ for (i = 0; i < npoints; i++) {
+ if (zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2), (void **) &var) == SUCCESS) {
+- SEPARATE_ZVAL((var));
+- convert_to_long(*var);
+- points[i].x = Z_LVAL_PP(var);
++ if (Z_TYPE_PP(var) != IS_LONG) {
++ zval lval;
++ lval = **var;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ points[i].x = Z_LVAL(lval);
++ } else {
++ points[i].x = Z_LVAL_PP(var);
++ }
+ }
+ if (zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2) + 1, (void **) &var) == SUCCESS) {
+- SEPARATE_ZVAL(var);
+- convert_to_long(*var);
+- points[i].y = Z_LVAL_PP(var);
++ if (Z_TYPE_PP(var) != IS_LONG) {
++ zval lval;
++ lval = **var;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ points[i].y = Z_LVAL(lval);
++ } else {
++ points[i].y = Z_LVAL_PP(var);
++ }
+ }
+ }
+
+@@ -4859,9 +4877,15 @@ PHP_FUNCTION(imageconvolution)
+
+ for (j=0; j<3; j++) {
+ if (zend_hash_index_find(Z_ARRVAL_PP(var), (j), (void **) &var2) == SUCCESS) {
+- SEPARATE_ZVAL(var2);
+- convert_to_double(*var2);
+- matrix[i][j] = (float)Z_DVAL_PP(var2);
++ if (Z_TYPE_PP(var2) != IS_DOUBLE) {
++ zval dval;
++ dval = **var;
++ zval_copy_ctor(&dval);
++ convert_to_double(&dval);
++ matrix[i][j] = (float)Z_DVAL(dval);
++ } else {
++ matrix[i][j] = (float)Z_DVAL_PP(var2);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must have a 3x3 matrix");
+ RETURN_FALSE;
+@@ -4954,28 +4978,60 @@ PHP_FUNCTION(imagecrop)
+ ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);
+
+ if (zend_hash_find(HASH_OF(z_rect), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
+- rect.x = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.x = Z_LVAL(lval);
++ } else {
++ rect.x = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "y", sizeof("x"), (void **)&tmp) != FAILURE) {
+- rect.y = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.y = Z_LVAL(lval);
++ } else {
++ rect.y = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "width", sizeof("width"), (void **)&tmp) != FAILURE) {
+- rect.width = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.width = Z_LVAL(lval);
++ } else {
++ rect.width = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing width");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "height", sizeof("height"), (void **)&tmp) != FAILURE) {
+- rect.height = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.height = Z_LVAL(lval);
++ } else {
++ rect.height = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing height");
+ RETURN_FALSE;
+@@ -5124,8 +5180,13 @@ PHP_FUNCTION(imageaffine)
+ affine[i] = Z_DVAL_PP(zval_affine_elem);
+ break;
+ case IS_STRING:
+- convert_to_double_ex(zval_affine_elem);
+- affine[i] = Z_DVAL_PP(zval_affine_elem);
++ {
++ zval dval;
++ dval = **zval_affine_elem;
++ zval_copy_ctor(&dval);
++ convert_to_double(&dval);
++ affine[i] = Z_DVAL(dval);
++ }
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
+@@ -5136,32 +5197,60 @@ PHP_FUNCTION(imageaffine)
+
+ if (z_rect != NULL) {
+ if (zend_hash_find(HASH_OF(z_rect), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
+- convert_to_long_ex(tmp);
+- rect.x = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.x = Z_LVAL(lval);
++ } else {
++ rect.x = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "y", sizeof("x"), (void **)&tmp) != FAILURE) {
+- convert_to_long_ex(tmp);
+- rect.y = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.y = Z_LVAL(lval);
++ } else {
++ rect.y = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "width", sizeof("width"), (void **)&tmp) != FAILURE) {
+- convert_to_long_ex(tmp);
+- rect.width = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.width = Z_LVAL(lval);
++ } else {
++ rect.width = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing width");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(z_rect), "height", sizeof("height"), (void **)&tmp) != FAILURE) {
+- convert_to_long_ex(tmp);
+- rect.height = Z_LVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_LONG) {
++ zval lval;
++ lval = **tmp;
++ zval_copy_ctor(&lval);
++ convert_to_long(&lval);
++ rect.height = Z_LVAL(lval);
++ } else {
++ rect.height = Z_LVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing height");
+ RETURN_FALSE;
+@@ -5211,16 +5300,30 @@ PHP_FUNCTION(imageaffinematrixget)
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array expected as options");
+ }
+ if (zend_hash_find(HASH_OF(options), "x", sizeof("x"), (void **)&tmp) != FAILURE) {
+- convert_to_double_ex(tmp);
+- x = Z_DVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_DOUBLE) {
++ zval dval;
++ dval = **tmp;
++ zval_copy_ctor(&dval);
++ convert_to_double(&dval);
++ x = Z_DVAL(dval);
++ } else {
++ x = Z_DVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing x position");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(HASH_OF(options), "y", sizeof("y"), (void **)&tmp) != FAILURE) {
+- convert_to_double_ex(tmp);
+- y = Z_DVAL_PP(tmp);
++ if (Z_TYPE_PP(tmp) != IS_DOUBLE) {
++ zval dval;
++ dval = **tmp;
++ zval_copy_ctor(&dval);
++ convert_to_double(&dval);
++ y = Z_DVAL(dval);
++ } else {
++ y = Z_DVAL_PP(tmp);
++ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position");
+ RETURN_FALSE;
+@@ -5300,8 +5403,13 @@ PHP_FUNCTION(imageaffinematrixconcat)
+ m1[i] = Z_DVAL_PP(tmp);
+ break;
+ case IS_STRING:
+- convert_to_double_ex(tmp);
+- m1[i] = Z_DVAL_PP(tmp);
++ {
++ zval dval;
++ dval = **tmp;
++ zval_copy_ctor(&dval);
++ convert_to_double(&dval);
++ m1[i] = Z_DVAL(dval);
++ }
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
+@@ -5317,8 +5425,13 @@ PHP_FUNCTION(imageaffinematrixconcat)
+ m2[i] = Z_DVAL_PP(tmp);
+ break;
+ case IS_STRING:
+- convert_to_double_ex(tmp);
+- m2[i] = Z_DVAL_PP(tmp);
++ {
++ zval dval;
++ dval = **tmp;
++ zval_copy_ctor(&dval);
++ convert_to_double(&dval);
++ m2[i] = Z_DVAL(dval);
++ }
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type for element %i", i);
+diff --git a/ext/gd/tests/bug66356.phpt b/ext/gd/tests/bug66356.phpt
+new file mode 100644
+index 0000000..f881494
+--- /dev/null
++++ b/ext/gd/tests/bug66356.phpt
+@@ -0,0 +1,22 @@
++--TEST--
++Bug #66356 (Heap Overflow Vulnerability in imagecrop())
++--SKIPIF--
++<?php
++ if(!extension_loaded('gd')){ die('skip gd extension not available'); }
++?>
++--FILE--
++<?php
++$img = imagecreatetruecolor(10, 10);
++$img = imagecrop($img, array("x" => "a", "y" => 0, "width" => 10, "height" => 10));
++$arr = array("x" => "a", "y" => "12b", "width" => 10, "height" => 10);
++$img = imagecrop($img, $arr);
++print_r($arr);
++?>
++--EXPECTF--
++Array
++(
++ [x] => a
++ [y] => 12b
++ [width] => 10
++ [height] => 10
++)
+--
+1.8.4.3
+
+From 8f4a5373bb71590352fd934028d6dde5bc18530b Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@php.net>
+Date: Sat, 28 Dec 2013 14:22:13 +0100
+Subject: [PATCH] Fixed bug #66356 (Heap Overflow Vulnerability in imagecrop())
+
+Initial fix was PHP stuff
+This one is libgd fix.
+
+- filter invalid crop size
+- dont try to copy on invalid position
+- fix crop size when out of src image
+- fix possible NULL deref
+- fix possible integer overfloow
+---
+ NEWS | 3 ++-
+ ext/gd/libgd/gd_crop.c | 52 ++++++++++++++++++++++++++++------------------
+ ext/gd/tests/bug66356.phpt | 22 ++++++++++++++++++--
+ 3 files changed, 54 insertions(+), 23 deletions(-)
+
+diff --git a/ext/gd/libgd/gd_crop.c b/ext/gd/libgd/gd_crop.c
+index f0b888a..90a99a6 100644
+--- a/ext/gd/libgd/gd_crop.c
++++ b/ext/gd/libgd/gd_crop.c
+@@ -44,6 +44,12 @@ gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop)
+ {
+ gdImagePtr dst;
+
++ /* check size */
++ if (crop->width<=0 || crop->height<=0) {
++ return NULL;
++ }
++
++ /* allocate the requested size (could be only partially filled) */
+ if (src->trueColor) {
+ dst = gdImageCreateTrueColor(crop->width, crop->height);
+ gdImageSaveAlpha(dst, 1);
+@@ -51,37 +57,43 @@ gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop)
+ dst = gdImageCreate(crop->width, crop->height);
+ gdImagePaletteCopy(dst, src);
+ }
++ if (dst == NULL) {
++ return NULL;
++ }
+ dst->transparent = src->transparent;
+
+- if (src->sx < (crop->x + crop->width -1)) {
+- crop->width = src->sx - crop->x + 1;
++ /* check position in the src image */
++ if (crop->x < 0 || crop->x>=src->sx || crop->y<0 || crop->y>=src->sy) {
++ return dst;
++ }
++
++ /* reduce size if needed */
++ if ((src->sx - crop->width) < crop->x) {
++ crop->width = src->sx - crop->x;
+ }
+- if (src->sy < (crop->y + crop->height -1)) {
+- crop->height = src->sy - crop->y + 1;
++ if ((src->sy - crop->height) < crop->y) {
++ crop->height = src->sy - crop->y;
+ }
++
+ #if 0
+ printf("rect->x: %i\nrect->y: %i\nrect->width: %i\nrect->height: %i\n", crop->x, crop->y, crop->width, crop->height);
+ #endif
+- if (dst == NULL) {
+- return NULL;
++ int y = crop->y;
++ if (src->trueColor) {
++ unsigned int dst_y = 0;
++ while (y < (crop->y + (crop->height - 1))) {
++ /* TODO: replace 4 w/byte per channel||pitch once available */
++ memcpy(dst->tpixels[dst_y++], src->tpixels[y++] + crop->x, crop->width * 4);
++ }
+ } else {
+- int y = crop->y;
+- if (src->trueColor) {
+- unsigned int dst_y = 0;
+- while (y < (crop->y + (crop->height - 1))) {
+- /* TODO: replace 4 w/byte per channel||pitch once available */
+- memcpy(dst->tpixels[dst_y++], src->tpixels[y++] + crop->x, crop->width * 4);
+- }
+- } else {
+- int x;
+- for (y = crop->y; y < (crop->y + (crop->height - 1)); y++) {
+- for (x = crop->x; x < (crop->x + (crop->width - 1)); x++) {
+- dst->pixels[y - crop->y][x - crop->x] = src->pixels[y][x];
+- }
++ int x;
++ for (y = crop->y; y < (crop->y + (crop->height - 1)); y++) {
++ for (x = crop->x; x < (crop->x + (crop->width - 1)); x++) {
++ dst->pixels[y - crop->y][x - crop->x] = src->pixels[y][x];
+ }
+ }
+- return dst;
+ }
++ return dst;
+ }
+
+ /**
+diff --git a/ext/gd/tests/bug66356.phpt b/ext/gd/tests/bug66356.phpt
+index f881494..2da91d6 100644
+--- a/ext/gd/tests/bug66356.phpt
++++ b/ext/gd/tests/bug66356.phpt
+@@ -7,12 +7,27 @@ Bug #66356 (Heap Overflow Vulnerability in imagecrop())
+ --FILE--
+ <?php
+ $img = imagecreatetruecolor(10, 10);
+-$img = imagecrop($img, array("x" => "a", "y" => 0, "width" => 10, "height" => 10));
++
++// POC #1
++var_dump(imagecrop($img, array("x" => "a", "y" => 0, "width" => 10, "height" => 10)));
++
+ $arr = array("x" => "a", "y" => "12b", "width" => 10, "height" => 10);
+-$img = imagecrop($img, $arr);
++var_dump(imagecrop($img, $arr));
+ print_r($arr);
++
++// POC #2
++var_dump(imagecrop($img, array("x" => 0, "y" => 0, "width" => -1, "height" => 10)));
++
++// POC #3
++var_dump(imagecrop($img, array("x" => -20, "y" => -20, "width" => 10, "height" => 10)));
++
++// POC #4
++var_dump(imagecrop($img, array("x" => 0x7fffff00, "y" => 0, "width" => 10, "height" => 10)));
++
+ ?>
+ --EXPECTF--
++resource(%d) of type (gd)
++resource(%d) of type (gd)
+ Array
+ (
+ [x] => a
+@@ -20,3 +35,6 @@ Array
+ [width] => 10
+ [height] => 10
+ )
++bool(false)
++resource(%d) of type (gd)
++resource(%d) of type (gd)
+\ No newline at end of file
+--
+1.8.4.3
+
+From 464c219ed4ebce6b9196cae308967ac7f7f58bde Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@php.net>
+Date: Sat, 28 Dec 2013 14:29:14 +0100
+Subject: [PATCH] minor fix on previous
+
+---
+ ext/gd/libgd/gd_crop.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ext/gd/libgd/gd_crop.c b/ext/gd/libgd/gd_crop.c
+index 90a99a6..bba425d 100644
+--- a/ext/gd/libgd/gd_crop.c
++++ b/ext/gd/libgd/gd_crop.c
+@@ -43,6 +43,7 @@ static int gdColorMatch(gdImagePtr im, int col1, int col2, float threshold);
+ gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop)
+ {
+ gdImagePtr dst;
++ int y;
+
+ /* check size */
+ if (crop->width<=0 || crop->height<=0) {
+@@ -78,7 +79,7 @@ gdImagePtr gdImageCrop(gdImagePtr src, const gdRectPtr crop)
+ #if 0
+ printf("rect->x: %i\nrect->y: %i\nrect->width: %i\nrect->height: %i\n", crop->x, crop->y, crop->width, crop->height);
+ #endif
+- int y = crop->y;
++ y = crop->y;
+ if (src->trueColor) {
+ unsigned int dst_y = 0;
+ while (y < (crop->y + (crop->height - 1))) {
+--
+1.8.4.3
+