Skip to content
Permalink
Browse files Browse the repository at this point in the history
Fixed bug #66356 (Heap Overflow Vulnerability in imagecrop())
And also fixed the bug: arguments are altered after some calls
  • Loading branch information
laruence committed Dec 27, 2013
1 parent 6414fe2 commit 2938329
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 37 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -29,6 +29,7 @@ PHP NEWS
. Fixed bug #66229 (128.0.0.0/16 isn't reserved any longer). (Adam)

- GD:
. Fixed bug #66356 (Heap Overflow Vulnerability in imagecrop()). (Laruence)
. Fixed bug #64405 (Use freetype-config for determining freetype2 dir(s)).
(Adam)

Expand Down
181 changes: 147 additions & 34 deletions ext/gd/gd.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
22 changes: 22 additions & 0 deletions 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
)
6 changes: 3 additions & 3 deletions main/php_version.h
Expand Up @@ -2,7 +2,7 @@
/* edit configure.in to change version number */
#define PHP_MAJOR_VERSION 5
#define PHP_MINOR_VERSION 5
#define PHP_RELEASE_VERSION 8
#define PHP_RELEASE_VERSION 5
#define PHP_EXTRA_VERSION "-dev"
#define PHP_VERSION "5.5.8-dev"
#define PHP_VERSION_ID 50508
#define PHP_VERSION "5.5.5-dev"
#define PHP_VERSION_ID 50505

0 comments on commit 2938329

Please sign in to comment.