Commit dddbca6ec6c for php.net
commit dddbca6ec6ca83ddc610c1996c5c56cba22875ae
Author: lacatoire <la.catoire@gmail.com>
Date: Fri Sep 4 04:47:38 2026 +0100
ext/gd: report $size with the argument number of the function called
php_imagettftext_common() serves the bbox functions, where $size is
argument #1, and the drawing ones, where it is #2, but its two size
checks hardcode 2. imageftbbox(NAN, ...) therefore blamed $angle.
Also fix the upper bound itself: (double)LONG_MAX rounds up to 2^63, so
(double)LONG_MAX / 64 is 2^57 and the check let 2^57 through, whose
product with 64 is LONG_MAX + 1. The bound is now exclusive, and the
reported values use integer division, which gives the largest size that
is actually representable. The lower bound stays inclusive:
(double)LONG_MIN / 64 is exactly -2^57 and its product with 64 is
LONG_MIN.
Co-authored-by: NickSdot <32384907+NickSdot@users.noreply.github.com>
Close GH-23541
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 7f55b8bcc74..6a056287c45 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -3422,14 +3422,16 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode)
im = php_gd_libgdimageptr_from_zval_p(IM);
}
+ uint32_t ptsize_arg_num = mode == TTFTEXT_BBOX ? 1 : 2;
+
// FT_F26Dot6 is a signed long alias
- if (ptsize < (double)LONG_MIN / 64 || ptsize > (double)LONG_MAX / 64) {
- zend_argument_value_error(2, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (zend_long)((double)LONG_MIN / 64), (zend_long)((double)LONG_MAX / 64));
+ if (ptsize < (double)LONG_MIN / 64 || ptsize >= (double)LONG_MAX / 64) {
+ zend_argument_value_error(ptsize_arg_num, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (zend_long)(LONG_MIN / 64), (zend_long)(LONG_MAX / 64));
RETURN_THROWS();
}
if (UNEXPECTED(!zend_finite(ptsize))) {
- zend_argument_value_error(2, "must be finite");
+ zend_argument_value_error(ptsize_arg_num, "must be finite");
RETURN_THROWS();
}
diff --git a/ext/gd/tests/gh18243.phpt b/ext/gd/tests/gh18243.phpt
index 00698add614..de0ac1861fb 100644
--- a/ext/gd/tests/gh18243.phpt
+++ b/ext/gd/tests/gh18243.phpt
@@ -34,9 +34,16 @@
} catch (\ValueError $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}
+
+try {
+ imagettftext($im, 144115188075855872.0, 0, 15, 60, 0, $font, "");
+} catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+}
?>
--EXPECTF--
ValueError: imagettftext(): Argument #2 ($size) must be between %i and %d
ValueError: imagettftext(): Argument #2 ($size) must be between %i and %d
ValueError: imagettftext(): Argument #2 ($size) must be finite
ValueError: imagettftext(): Argument #2 ($size) must be between %i and %d
+ValueError: imagettftext(): Argument #2 ($size) must be between %i and %d
diff --git a/ext/gd/tests/imageftbbox_size_arg_num.phpt b/ext/gd/tests/imageftbbox_size_arg_num.phpt
new file mode 100644
index 00000000000..b968817c48c
--- /dev/null
+++ b/ext/gd/tests/imageftbbox_size_arg_num.phpt
@@ -0,0 +1,62 @@
+--TEST--
+The $size errors name the argument of the function that was called
+--EXTENSIONS--
+gd
+--SKIPIF--
+<?php
+if (!function_exists('imageftbbox')) die('skip imageftbbox() not available');
+?>
+--FILE--
+<?php
+$font = __DIR__ . '/Rochester-Regular.otf';
+$image = imagecreatetruecolor(100, 80);
+
+/* $size is argument #1 here */
+foreach ([NAN, INF, PHP_INT_MAX, PHP_INT_MIN] as $size) {
+ try {
+ imageftbbox($size, 0.0, $font, 'A');
+ } catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+ }
+ try {
+ imagettfbbox($size, 0.0, $font, 'A');
+ } catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+ }
+}
+
+/* and argument #2 here */
+foreach ([NAN, INF] as $size) {
+ try {
+ imagefttext($image, $size, 0.0, 15, 60, 0, $font, 'A');
+ } catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+ }
+ try {
+ imagettftext($image, $size, 0.0, 15, 60, 0, $font, 'A');
+ } catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+ }
+}
+
+/* the type error already agreed with the signature and still does */
+try {
+ imageftbbox('x', 0.0, $font, 'A');
+} catch (Throwable $e) {
+ echo $e::class, ': ', $e->getMessage(), "\n";
+}
+?>
+--EXPECTF--
+ValueError: imageftbbox(): Argument #1 ($size) must be finite
+ValueError: imagettfbbox(): Argument #1 ($size) must be finite
+ValueError: imageftbbox(): Argument #1 ($size) must be between %i and %d
+ValueError: imagettfbbox(): Argument #1 ($size) must be between %i and %d
+ValueError: imageftbbox(): Argument #1 ($size) must be between %i and %d
+ValueError: imagettfbbox(): Argument #1 ($size) must be between %i and %d
+ValueError: imageftbbox(): Argument #1 ($size) must be between %i and %d
+ValueError: imagettfbbox(): Argument #1 ($size) must be between %i and %d
+ValueError: imagefttext(): Argument #2 ($size) must be finite
+ValueError: imagettftext(): Argument #2 ($size) must be finite
+ValueError: imagefttext(): Argument #2 ($size) must be between %i and %d
+ValueError: imagettftext(): Argument #2 ($size) must be between %i and %d
+TypeError: imageftbbox(): Argument #1 ($size) must be of type float, string given