mirror of
https://github.com/WordPress/WordPress.git
synced 2026-06-19 07:37:07 +00:00
REST API: Fix rest_is_integer() returning false for large integers.
The previous `round( (float) $maybe_integer ) === (float) $maybe_integer` check rejected large integers on PHP 8.4. The check itself was fragile: a PHP `float` (a 64-bit IEEE-754 double) can represent every integer exactly only up to 2^53, so casting larger values is lossy. Nevertheless, that lossiness alone did not reject anything, since both sides of the comparison were munged identically. What actually broke it was a `round()` regression in PHP 8.4, where `round( (float) $x )` can return a value different from `(float) $x` for certain numbers. That inequality caused canonical integers still valid for a `BIGINT UNSIGNED` column (such as unusually high post IDs) to be incorrectly rejected by REST validation, only on PHP 8.4+. The function now short-circuits returning true for native integers and canonical integer strings so that integer-like values of any magnitude are detected correctly. Decimal and scientific-notation strings (and floats) retain their historical behavior, including the existing float comparison, now rewritten as a `floor()` check whose strict equality compares a float to its own floor and is therefore exact. The limitations around `PHP_INT_MAX` and fractional magnitudes beyond `2 ** 53` are documented on the function, and the data provider gains coverage for large integers, negative floats, and scientific notation. Developed in https://github.com/WordPress/wordpress-develop/pull/11893. Follow-up to r48306. Props siliconforks, gautam23, westonruter, kevinfodness, mboynes, desrosj. Fixes #65271. Built from https://develop.svn.wordpress.org/trunk@62474 git-svn-id: http://core.svn.wordpress.org/trunk@61755 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
@@ -1564,13 +1564,43 @@ function rest_is_boolean( $maybe_bool ) {
|
||||
/**
|
||||
* Determines if a given value is integer-like.
|
||||
*
|
||||
* This reports whether the value represents an integer; it does not guarantee that the
|
||||
* value can be represented as a native PHP integer. Values whose magnitude exceeds
|
||||
* `PHP_INT_MAX` are still reported as integer-like, even though the `(int)` cast that
|
||||
* {@see rest_sanitize_value_from_schema()} applies for the 'integer' type cannot round-trip
|
||||
* them: an out-of-range numeric *string* saturates to `PHP_INT_MAX` or `PHP_INT_MIN`, while
|
||||
* an out-of-range *float* is an undefined conversion in PHP that yields an arbitrary wrapped
|
||||
* value. Likewise, a numeric value with a fractional part that is too large for the fraction
|
||||
* to be represented as a float (greater than 2 ** 53) is reported as integer-like.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @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;
|
||||
|
||||
/*
|
||||
* The strict equality here is not the unreliable "are two computed floats equal" comparison
|
||||
* (e.g. 0.1 + 0.2 === 0.3, which is false). It compares a float to its own floor() to ask
|
||||
* "does this float have a fractional part?". A float is whole exactly when it equals its floor,
|
||||
* so the comparison is exact and safe regardless of floating-point representation error.
|
||||
*/
|
||||
return floor( $float_value ) === $float_value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '7.1-alpha-62473';
|
||||
$wp_version = '7.1-alpha-62474';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
||||
Reference in New Issue
Block a user