diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 5548ecf5c6f45..dc8a8d938eac4 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -1569,8 +1569,22 @@ 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 ) { - return is_numeric( $maybe_integer ) && round( (float) $maybe_integer ) === (float) $maybe_integer; +function rest_is_integer( $maybe_integer ): bool { + 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. + if ( ! is_numeric( $maybe_integer ) ) { + return false; + } + $float_value = (float) $maybe_integer; + return floor( $float_value ) === $float_value; } /** diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 90de3e13eecea..cfc53bd434114 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 * @@ -2307,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, @@ -2341,6 +2347,14 @@ public function data_rest_is_integer() { false, '5.5', ), + array( + false, + -5.5, + ), + array( + false, + '-5.5', + ), array( false, array(), @@ -2349,6 +2363,40 @@ public function data_rest_is_integer() { false, true, ), + array( + true, + '15e0', + ), + array( + true, + '15e+0', + ), + array( + true, + '15e-0', + ), + array( + false, + '15e-1', + ), + + // The following values failed with PHP 8.4 when rest_is_integer() used round() in its implementation. + array( + true, + 2 ** 52, + ), + array( + true, + 2 ** 52 + 2, + ), + array( + true, + '4503599627370496', // 2 ** 52 + ), + array( + true, + '4503599627370498', // 2 ** 52 + 2 + ), ); }