CVE-2014-2020 (Other, published 2014-02-18T11:55Z)
Description: value: ext/gd/gd.c in PHP 5.5.x before 5.5.9 does not check data types, which might allow remote attackers to obtain sensitive information by using a (1) string or (2) array data type in place of a numeric data type, as demonstrated by an imagecrop function call with a string for the x dimension value, a different vulnerability than CVE-2013-7226.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-189 \u2014 Numeric Errors
Weaknesses in this category are related to improper calculation or conversion of numbers.
Repository: https://github.com/php/php-src
Files changed:
NEWS
ext/gd/gd.c
ext/gd/tests/bug66356.phpt
main/php_version.h
Commit message: Fixed bug #66356 (Heap Overflow Vulnerability in imagecrop())

And also fixed the bug: arguments are altered after some calls


Vulnerable code:
		convert_to_long_ex(item);

		stylearr[index++] = Z_LVAL_PP(item);
			SEPARATE_ZVAL((var));
			convert_to_long(*var);
			points[i].x = Z_LVAL_PP(var);
			SEPARATE_ZVAL(var);
			convert_to_long(*var);
			points[i].y = Z_LVAL_PP(var);
					SEPARATE_ZVAL(var2);
					convert_to_double(*var2);
					matrix[i][j] = (float)Z_DVAL_PP(var2);
		rect.x = Z_LVAL_PP(tmp);
		rect.y = Z_LVAL_PP(tmp);
		rect.width = Z_LVAL_PP(tmp);
		rect.height = Z_LVAL_PP(tmp);
					convert_to_double_ex(zval_affine_elem);
					affine[i] = Z_DVAL_PP(zval_affine_elem);
			convert_to_long_ex(tmp);
			rect.x = Z_LVAL_PP(tmp);
			convert_to_long_ex(tmp);
			rect.y = Z_LVAL_PP(tmp);
			convert_to_long_ex(tmp);
			rect.width = Z_LVAL_PP(tmp);
			convert_to_long_ex(tmp);
			rect.height = Z_LVAL_PP(tmp);
				convert_to_double_ex(tmp);
				x = Z_DVAL_PP(tmp);
				convert_to_double_ex(tmp);
				y = Z_DVAL_PP(tmp);
					convert_to_double_ex(tmp);
					m1[i] = Z_DVAL_PP(tmp);
					convert_to_double_ex(tmp);
					m2[i] = Z_DVAL_PP(tmp);
#define PHP_RELEASE_VERSION 8
#define PHP_VERSION "5.5.8-dev"
#define PHP_VERSION_ID 50508

Fixed code:
  . Fixed bug #66356 (Heap Overflow Vulnerability in imagecrop()). (Laruence)
		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);
		}
			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 (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);
			}
					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);
					}
		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);
		}
		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);
		}
		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);
		}
		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);
		}
					{
						zval dval;
						dval = **zval_affine_elem;
						zval_copy_ctor(&dval);
						convert_to_double(&dval);
						affine[i] = Z_DVAL(dval);
					}
			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);
			}
			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);
			}
			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);
			}
			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);
			}
				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);
				}
				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);
				}
					{
						zval dval;
						dval = **tmp;
						zval_copy_ctor(&dval);
						convert_to_double(&dval);
						m1[i] = Z_DVAL(dval);
					}
					{
						zval dval;
						dval = **tmp;
						zval_copy_ctor(&dval);
						convert_to_double(&dval);
						m2[i] = Z_DVAL(dval);
					}
--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
)
#define PHP_RELEASE_VERSION 5
#define PHP_VERSION "5.5.5-dev"
#define PHP_VERSION_ID 50505