diff --git a/NEWS b/NEWS index 1569f2e064d5..78265622e7d7 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,8 @@ PHP NEWS - GD: . Fixed imageaffinematrixget() and imageaffinematrixconcat() reporting the wrong argument in error messages. (Weilin Du) + . Fixed imageaffinematrixget() to enforce the documented array|float type + for the $options parameter. (Weilin Du) - Intl: . Fixed grapheme_strrev() treating UBRK_DONE as a byte index and leaving diff --git a/UPGRADING b/UPGRADING index a99299098f98..5054e0a4d81f 100644 --- a/UPGRADING +++ b/UPGRADING @@ -51,6 +51,9 @@ PHP 8.6 UPGRADE NOTES - GD: . imagesetstyle(), imagefilter() and imagecrop() filter their array arguments types / values and raise a TypeError / ValueError accordingly. + . imageaffinematrixget() now enforces the documented array|float type for the + $options parameter, including the corresponding weak and strict typing + behavior. - GMP: . GMP power and shift operators now throw a ValueError when GMP right operands diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index a83b4f882fe2..dc2a35cc9c2c 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -185,6 +185,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES . Added zend_ast_call_get_args() to fetch the argument node from any call node. . Added Z_PARAM_ENUM(). + . Added PHP_GD_Z_PARAM_ARRAY_HT_OR_DOUBLE() in ext/gd to parse array|float + arguments into either a HashTable pointer or a double. . Added zend_enum_fetch_case_id(). . Added zend_enum_get_case_by_id(). . Added zend_bin2hex() and zend_bin2hex_str() as helper functions to remove diff --git a/ext/gd/gd.c b/ext/gd/gd.c index f178cea1d799..48f594663b3e 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -4152,37 +4152,51 @@ PHP_FUNCTION(imageaffine) } /* }}} */ +#define PHP_GD_Z_PARAM_ARRAY_HT_OR_DOUBLE(dest_ht, dest_double) \ + Z_PARAM_PROLOGUE(0, 0); \ + if (EXPECTED(Z_TYPE_P(_arg) == IS_ARRAY)) { \ + dest_ht = Z_ARRVAL_P(_arg); \ + } else { \ + dest_ht = NULL; \ + if (UNEXPECTED(!zend_parse_arg_double(_arg, &dest_double, NULL, false, _i))) { \ + zend_argument_type_error(_i, "must be of type array|float, %s given", zend_zval_value_name(_arg)); \ + _error_code = ZPP_ERROR_FAILURE; \ + break; \ + } \ + } + /* {{{ Return an image containing the affine tramsformed src image, using an optional clipping area */ PHP_FUNCTION(imageaffinematrixget) { double affine[6]; + double dval_option = 0.0; zend_long type; - zval *options = NULL; + HashTable *options; zval *tmp; int res = GD_FALSE; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(type) - Z_PARAM_ZVAL(options) + PHP_GD_Z_PARAM_ARRAY_HT_OR_DOUBLE(options, dval_option) ZEND_PARSE_PARAMETERS_END(); switch((gdAffineStandardMatrix)type) { case GD_AFFINE_TRANSLATE: case GD_AFFINE_SCALE: { double x, y; - if (Z_TYPE_P(options) != IS_ARRAY) { + if (options == NULL) { zend_argument_type_error(2, "must be of type array when using translate or scale"); RETURN_THROWS(); } - if ((tmp = zend_hash_str_find(Z_ARRVAL_P(options), "x", sizeof("x") - 1)) != NULL) { + if ((tmp = zend_hash_str_find(options, "x", sizeof("x") - 1)) != NULL) { x = zval_get_double(tmp); } else { zend_argument_value_error(2, "must have an \"x\" key"); RETURN_THROWS(); } - if ((tmp = zend_hash_str_find(Z_ARRVAL_P(options), "y", sizeof("y") - 1)) != NULL) { + if ((tmp = zend_hash_str_find(options, "y", sizeof("y") - 1)) != NULL) { y = zval_get_double(tmp); } else { zend_argument_value_error(2, "must have a \"y\" key"); @@ -4202,7 +4216,11 @@ PHP_FUNCTION(imageaffinematrixget) case GD_AFFINE_SHEAR_VERTICAL: { double angle; - angle = zval_get_double(options); + if (options != NULL) { + zend_argument_type_error(2, "must be of type float when using rotate or shear"); + RETURN_THROWS(); + } + angle = dval_option; if (type == GD_AFFINE_SHEAR_HORIZONTAL) { res = gdAffineShearHorizontal(affine, angle); diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php index 0632724b44f3..6a5882c8be75 100644 --- a/ext/gd/gd.stub.php +++ b/ext/gd/gd.stub.php @@ -762,11 +762,10 @@ function imagescale(GdImage $image, int $width, int $height = -1, int $mode = IM function imageaffine(GdImage $image, array $affine, ?array $clip = null): GdImage|false {} /** - * @param array|float $options * @refcount 1 * @return array|false */ -function imageaffinematrixget(int $type, $options): array|false {} +function imageaffinematrixget(int $type, array|float $options): array|false {} /** * @return array|false diff --git a/ext/gd/gd_arginfo.h b/ext/gd/gd_arginfo.h index 6b6327fd682f..978a7744ec28 100644 --- a/ext/gd/gd_arginfo.h +++ b/ext/gd/gd_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit gd.stub.php instead. - * Stub hash: 2cdc0b485d9b62bb9021973d3c8cce0169b21ac0 */ + * Stub hash: 21f8a978b8e54da880315dd9dfeecaf0f7d5593b */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -538,7 +538,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageaffinematrixget, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) - ZEND_ARG_INFO(0, options) + ZEND_ARG_TYPE_MASK(0, options, MAY_BE_ARRAY|MAY_BE_DOUBLE, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageaffinematrixconcat, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE) diff --git a/ext/gd/tests/bug67248.phpt b/ext/gd/tests/bug67248.phpt index 5f00b94fadcd..9dbbca9fc68c 100644 --- a/ext/gd/tests/bug67248.phpt +++ b/ext/gd/tests/bug67248.phpt @@ -17,55 +17,10 @@ for($i=0;$i<7;$i++) { } ?> --EXPECTF-- -!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array when using translate or scale -!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array when using translate or scale - -Warning: Object of class stdClass could not be converted to float in %s on line %d -array(6) { - [0]=> - float(%f) - [1]=> - float(%f) - [2]=> - float(%f) - [3]=> - float(%f) - [4]=> - float(0) - [5]=> - float(0) -} - -Warning: Object of class stdClass could not be converted to float in %s on line %d -array(6) { - [0]=> - float(1) - [1]=> - float(0) - [2]=> - float(%f) - [3]=> - float(1) - [4]=> - float(0) - [5]=> - float(0) -} - -Warning: Object of class stdClass could not be converted to float in %s on line %d -array(6) { - [0]=> - float(1) - [1]=> - float(%f) - [2]=> - float(0) - [3]=> - float(1) - [4]=> - float(0) - [5]=> - float(0) -} -!! [ValueError] imageaffinematrixget(): Argument #1 ($type) must be a valid element type -!! [ValueError] imageaffinematrixget(): Argument #1 ($type) must be a valid element type +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +!! [TypeError] imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given diff --git a/ext/gd/tests/bug71952.phpt b/ext/gd/tests/bug71952.phpt index fa583fc795e8..cc86984e9ae0 100644 --- a/ext/gd/tests/bug71952.phpt +++ b/ext/gd/tests/bug71952.phpt @@ -5,8 +5,13 @@ gd --FILE-- getMessage(), "\n"; +} var_dump($vals[0]); ?> --EXPECT-- +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, string given string(200) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" diff --git a/ext/gd/tests/imageaffinematrixget_zpp_strict_mode.phpt b/ext/gd/tests/imageaffinematrixget_zpp_strict_mode.phpt new file mode 100644 index 000000000000..1fe66b0e516f --- /dev/null +++ b/ext/gd/tests/imageaffinematrixget_zpp_strict_mode.phpt @@ -0,0 +1,66 @@ +--TEST-- +imageaffinematrixget() array|float parameter coercions (strict mode) +--EXTENSIONS-- +gd +--FILE-- + null, + 'false' => false, + 'true' => true, + 'int' => 42, + 'float' => 73.5, + 'numeric string' => '15', + 'non-numeric string' => 'string', + 'array' => [], + 'object' => new stdClass(), +]; + +foreach ($values as $name => $value) { + echo "$name:\n"; + try { + imageaffinematrixget(IMG_AFFINE_ROTATE, $value); + echo "accepted\n"; + } catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; + } +} + +echo "array for translate:\n"; +imageaffinematrixget(IMG_AFFINE_TRANSLATE, ['x' => 1, 'y' => 2]); +echo "accepted\n"; + +echo "float for translate:\n"; +try { + imageaffinematrixget(IMG_AFFINE_TRANSLATE, 1.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +null: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, null given +false: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, false given +true: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, true given +int: +accepted +float: +accepted +numeric string: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, string given +non-numeric string: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, string given +array: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type float when using rotate or shear +object: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +array for translate: +accepted +float for translate: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array when using translate or scale diff --git a/ext/gd/tests/imageaffinematrixget_zpp_weak_mode.phpt b/ext/gd/tests/imageaffinematrixget_zpp_weak_mode.phpt new file mode 100644 index 000000000000..ffd5523fb83b --- /dev/null +++ b/ext/gd/tests/imageaffinematrixget_zpp_weak_mode.phpt @@ -0,0 +1,66 @@ +--TEST-- +imageaffinematrixget() array|float parameter coercions (weak mode) +--EXTENSIONS-- +gd +--FILE-- + null, + 'false' => false, + 'true' => true, + 'int' => 42, + 'float' => 73.5, + 'numeric string' => '15', + 'non-numeric string' => 'string', + 'array' => [], + 'object' => new stdClass(), +]; + +foreach ($values as $name => $value) { + echo "$name:\n"; + try { + imageaffinematrixget(IMG_AFFINE_ROTATE, $value); + echo "accepted\n"; + } catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; + } +} + +echo "array for translate:\n"; +imageaffinematrixget(IMG_AFFINE_TRANSLATE, ['x' => 1, 'y' => 2]); +echo "accepted\n"; + +echo "float for translate:\n"; +try { + imageaffinematrixget(IMG_AFFINE_TRANSLATE, 1.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +?> +--EXPECTF-- +null: + +Deprecated: imageaffinematrixget(): Passing null to parameter #2 ($options) of type array|float is deprecated in %s on line %d +accepted +false: +accepted +true: +accepted +int: +accepted +float: +accepted +numeric string: +accepted +non-numeric string: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, string given +array: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type float when using rotate or shear +object: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, stdClass given +array for translate: +accepted +float for translate: +TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array when using translate or scale