Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 24 additions & 6 deletions ext/gd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future PR: Ideally this should use a stricter variant as tmp could be an object of an array and still pass.

} 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");
Expand All @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions ext/gd/gd.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<int, float>|false
*/
function imageaffinematrixget(int $type, $options): array|false {}
function imageaffinematrixget(int $type, array|float $options): array|false {}

/**
* @return array<int, float>|false
Expand Down
4 changes: 2 additions & 2 deletions ext/gd/gd_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 7 additions & 52 deletions ext/gd/tests/bug67248.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion ext/gd/tests/bug71952.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ gd
--FILE--
<?php
$vals=[str_repeat("A","200"),0,1,2,3,4,5,6,7,8,9];
imageaffinematrixget(4,$vals[0]);
try {
imageaffinematrixget(4, $vals[0]);
} catch (TypeError $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}
var_dump($vals[0]);
?>
--EXPECT--
TypeError: imageaffinematrixget(): Argument #2 ($options) must be of type array|float, string given
string(200) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
66 changes: 66 additions & 0 deletions ext/gd/tests/imageaffinematrixget_zpp_strict_mode.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--TEST--
imageaffinematrixget() array|float parameter coercions (strict mode)
--EXTENSIONS--
gd
--FILE--
<?php

declare(strict_types=1);

$values = [
'null' => 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
66 changes: 66 additions & 0 deletions ext/gd/tests/imageaffinematrixget_zpp_weak_mode.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--TEST--
imageaffinematrixget() array|float parameter coercions (weak mode)
--EXTENSIONS--
gd
--FILE--
<?php

$values = [
'null' => 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
Loading