From 9f94fe05015ed5415f735b3e2a80894be395b651 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 11:51:14 -0300 Subject: [PATCH 01/10] Use floor() instead of round() in rest_is_integer() --- src/wp-includes/rest-api.php | 2 +- tests/phpunit/tests/rest-api.php | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 5548ecf5c6f45..877262f12f407 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -1570,7 +1570,7 @@ function rest_is_boolean( $maybe_bool ) { * @return bool True if an integer, otherwise false. */ function rest_is_integer( $maybe_integer ) { - return is_numeric( $maybe_integer ) && round( (float) $maybe_integer ) === (float) $maybe_integer; + return is_numeric( $maybe_integer ) && floor( (float) $maybe_integer ) === (float) $maybe_integer; } /** diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 90de3e13eecea..d3153af285ed7 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2352,6 +2352,31 @@ public function data_rest_is_integer() { ); } + /** + * @ticket 65271 + * + * @dataProvider data_rest_is_integer_large_values + * + * @param mixed $value The value to check. + */ + public function test_rest_is_integer_large_values( $value ) { + $this->assertTrue( rest_is_integer( $value ) ); + } + + public function data_rest_is_integer_large_values() { + /* + * These values failed with PHP 8.4 when rest_is_integer() used round() in its implementation. + */ + return array( + array( + 2 ** 52, + ), + array( + 2 ** 52 + 2, + ), + ); + } + /** * @ticket 50300 * From f420494ed2de97cd9844fad86414bb1b1479ef52 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 15:37:14 -0300 Subject: [PATCH 02/10] Handle int and string values in separate branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change suggested by @westonruter and Claude Opus 4.7. --- src/wp-includes/rest-api.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 877262f12f407..2f9439f4200e4 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -1570,6 +1570,16 @@ function rest_is_boolean( $maybe_bool ) { * @return bool True if an integer, otherwise false. */ function rest_is_integer( $maybe_integer ) { + if ( is_int( $maybe_integer ) ) { + return true; + } + + // A canonical integer string of any magnitude — verified without float conversion. + if ( is_string( $maybe_integer ) && preg_match( '/^\s*[+-]?[0-9]+\s*$/', $maybe_integer ) ) { + return true; + } + + // Decimal and scientific-notation strings (and floats) keep their historical behavior. return is_numeric( $maybe_integer ) && floor( (float) $maybe_integer ) === (float) $maybe_integer; } From d1b2b41cce5aa88a258b4843185c0a503d35507b Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 15:39:41 -0300 Subject: [PATCH 03/10] Add some tests for scientific notation and negative floats --- tests/phpunit/tests/rest-api.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index d3153af285ed7..b2d8ab6425de0 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2341,6 +2341,14 @@ public function data_rest_is_integer() { false, '5.5', ), + array( + false, + -5.5, + ), + array( + false, + '-5.5', + ), array( false, array(), @@ -2349,6 +2357,22 @@ public function data_rest_is_integer() { false, true, ), + array( + true, + '15e0', + ), + array( + true, + '15e+0', + ), + array( + true, + '15e-0', + ), + array( + false, + '15e-1', + ) ); } From e5757155c78d3238408adbe73a81ecae0337ab4a Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 16:00:19 -0300 Subject: [PATCH 04/10] Add trailing comma for array --- tests/phpunit/tests/rest-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index b2d8ab6425de0..11da1c1c1878e 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2372,7 +2372,7 @@ public function data_rest_is_integer() { array( false, '15e-1', - ) + ), ); } From fc92eb41ea85db448f86f623a74fbf08d39832d3 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 16:02:56 -0300 Subject: [PATCH 05/10] Add tests to the existing data_rest_is_integer data provider --- tests/phpunit/tests/rest-api.php | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 11da1c1c1878e..9ca7735848dc1 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2291,6 +2291,7 @@ public function data_rest_sanitize_array() { /** * @ticket 51146 + * @ticket 65271 * * @dataProvider data_rest_is_integer * @@ -2373,29 +2374,16 @@ public function data_rest_is_integer() { false, '15e-1', ), - ); - } - /** - * @ticket 65271 - * - * @dataProvider data_rest_is_integer_large_values - * - * @param mixed $value The value to check. - */ - public function test_rest_is_integer_large_values( $value ) { - $this->assertTrue( rest_is_integer( $value ) ); - } - - public function data_rest_is_integer_large_values() { - /* - * These values failed with PHP 8.4 when rest_is_integer() used round() in its implementation. - */ - return array( + /* + * These values failed with PHP 8.4 when rest_is_integer() used round() in its implementation. + */ array( + true, 2 ** 52, ), array( + true, 2 ** 52 + 2, ), ); From 4dd3b89dc584a0d4e9d0474a9133b133448e1007 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 16:06:41 -0300 Subject: [PATCH 06/10] Add some big integer string tests --- tests/phpunit/tests/rest-api.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 9ca7735848dc1..fc28dc3511dd9 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2386,6 +2386,14 @@ public function data_rest_is_integer() { true, 2 ** 52 + 2, ), + array( + true, + '4503599627370496', // 2 ** 52 + ), + array( + true, + '4503599627370498', // 2 ** 52 + 2 + ), ); } From 86589fc9d7fabd4fd3cd3512666305ef82a7d130 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 16:11:35 -0300 Subject: [PATCH 07/10] Refactor to avoid duplicating the cast to float --- src/wp-includes/rest-api.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 2f9439f4200e4..2e0e1c746b3df 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -1580,7 +1580,11 @@ function rest_is_integer( $maybe_integer ) { } // Decimal and scientific-notation strings (and floats) keep their historical behavior. - return is_numeric( $maybe_integer ) && floor( (float) $maybe_integer ) === (float) $maybe_integer; + if ( ! is_numeric( $maybe_integer ) ) { + return false; + } + $float_value = (float) $maybe_integer; + return floor( $float_value ) === $float_value; } /** From aadc2056e7766f3c4ce7bfda1fb584739d445fc4 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 16:32:05 -0300 Subject: [PATCH 08/10] Add phpdoc and return type to data_rest_is_integer --- tests/phpunit/tests/rest-api.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index fc28dc3511dd9..cda66fbbc2c6b 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2308,7 +2308,12 @@ public function test_rest_is_integer( $expected, $value ) { } } - public function data_rest_is_integer() { + /** + * Data provider for {@see self::test_rest_is_integer()}. + * + * @return list + */ + public function data_rest_is_integer(): array { return array( array( true, From 8c2853187524cc7456fd14961f2e795f14df2c80 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 16:33:59 -0300 Subject: [PATCH 09/10] Tweak comment --- tests/phpunit/tests/rest-api.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index cda66fbbc2c6b..cfc53bd434114 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -2380,9 +2380,7 @@ public function data_rest_is_integer(): array { '15e-1', ), - /* - * These values failed with PHP 8.4 when rest_is_integer() used round() in its implementation. - */ + // The following values failed with PHP 8.4 when rest_is_integer() used round() in its implementation. array( true, 2 ** 52, From 6083ed13d2d59e992d3111e1edb174482192b3d2 Mon Sep 17 00:00:00 2001 From: siliconforks Date: Wed, 20 May 2026 17:53:43 -0300 Subject: [PATCH 10/10] Add return type for rest_is_integer() --- src/wp-includes/rest-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 2e0e1c746b3df..dc8a8d938eac4 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -1569,7 +1569,7 @@ function rest_is_boolean( $maybe_bool ) { * @param mixed $maybe_integer The value being evaluated. * @return bool True if an integer, otherwise false. */ -function rest_is_integer( $maybe_integer ) { +function rest_is_integer( $maybe_integer ): bool { if ( is_int( $maybe_integer ) ) { return true; }