Media: Fix `TypeError` and improve `wp_exif_frac2dec()` to only return `int` or `float`.
For certain images, `wp_exif_frac2dec()` unexpectedly returned a string instead of `int` or `float`. This can occur when an image is missing meta and calls the function with `'0/0'`. For those images, a fatal error was thrown on PHP 8.0+: {{{ TypeError: round(): Argument #1 ($num) must be of type int|float, string given }}} Upon deeper review, inconsistent and unexpected results were returned from different types of input values passed to the function. Changes are: * Maintains backwards-compatibility for valid input values. * Fixes handling of invalid input values by bailing out to return the documented type of `int|float` by returning `0`. * Improves the fractional conditional check. * Improves the calculated fraction handling to ensure (a) the numerator and denominator are both numeric and (b) the denominator is not equal to zero. * Safeguards the behavior via tests for all possible ways code could flow through the function. * Safeguards the backwards-compatibility of the `wp_read_image_metadata()` by adding some defensive coding around the calls to the `wp_exif_frac2dec()` function. These changes fix the fatal error and make the function more secure, stable, and predictable while maintaining backwards-compatibility for valid input values. Follow-up to [6313], [9119], [22319], [28367], [45611], [47287]. Props adamsilverstein, jrf, peterwilsoncc, praem90, stevegs, tobiasbg. Fixes #54385. Built from https://develop.svn.wordpress.org/trunk@52269 git-svn-id: http://core.svn.wordpress.org/trunk@51861 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
2f6cf4ba81
commit
677e6e5b13
|
@ -646,19 +646,40 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
|
||||||
*
|
*
|
||||||
* @since 2.5.0
|
* @since 2.5.0
|
||||||
*
|
*
|
||||||
* @param string $str
|
* @param string $str Fraction string.
|
||||||
* @return int|float
|
* @return int|float Returns calculated fraction or integer 0 on invalid input.
|
||||||
*/
|
*/
|
||||||
function wp_exif_frac2dec( $str ) {
|
function wp_exif_frac2dec( $str ) {
|
||||||
if ( false === strpos( $str, '/' ) ) {
|
if ( ! is_scalar( $str ) || is_bool( $str ) ) {
|
||||||
return $str;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! is_string( $str ) ) {
|
||||||
|
return $str; // This can only be an integer or float, so this is fine.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fractions passed as a string must contain a single `/`.
|
||||||
|
if ( substr_count( $str, '/' ) !== 1 ) {
|
||||||
|
if ( is_numeric( $str ) ) {
|
||||||
|
return (float) $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
list( $numerator, $denominator ) = explode( '/', $str );
|
list( $numerator, $denominator ) = explode( '/', $str );
|
||||||
if ( ! empty( $denominator ) ) {
|
|
||||||
return $numerator / $denominator;
|
// Both the numerator and the denominator must be numbers.
|
||||||
|
if ( ! is_numeric( $numerator ) || ! is_numeric( $denominator ) ) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return $str;
|
|
||||||
|
// The denominator must not be zero.
|
||||||
|
if ( 0 == $denominator ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison -- Deliberate loose comparison.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $numerator / $denominator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -840,7 +861,7 @@ function wp_read_image_metadata( $file ) {
|
||||||
if ( empty( $meta['copyright'] ) && ! empty( $exif['Copyright'] ) ) {
|
if ( empty( $meta['copyright'] ) && ! empty( $exif['Copyright'] ) ) {
|
||||||
$meta['copyright'] = trim( $exif['Copyright'] );
|
$meta['copyright'] = trim( $exif['Copyright'] );
|
||||||
}
|
}
|
||||||
if ( ! empty( $exif['FNumber'] ) ) {
|
if ( ! empty( $exif['FNumber'] ) && is_scalar( $exif['FNumber'] ) ) {
|
||||||
$meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 );
|
$meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 );
|
||||||
}
|
}
|
||||||
if ( ! empty( $exif['Model'] ) ) {
|
if ( ! empty( $exif['Model'] ) ) {
|
||||||
|
@ -850,15 +871,21 @@ function wp_read_image_metadata( $file ) {
|
||||||
$meta['created_timestamp'] = wp_exif_date2ts( $exif['DateTimeDigitized'] );
|
$meta['created_timestamp'] = wp_exif_date2ts( $exif['DateTimeDigitized'] );
|
||||||
}
|
}
|
||||||
if ( ! empty( $exif['FocalLength'] ) ) {
|
if ( ! empty( $exif['FocalLength'] ) ) {
|
||||||
|
$meta['focal_length'] = (string) $exif['FocalLength'];
|
||||||
|
if ( is_scalar( $exif['FocalLength'] ) ) {
|
||||||
$meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] );
|
$meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
|
if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
|
||||||
$meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings'];
|
$meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings'];
|
||||||
$meta['iso'] = trim( $meta['iso'] );
|
$meta['iso'] = trim( $meta['iso'] );
|
||||||
}
|
}
|
||||||
if ( ! empty( $exif['ExposureTime'] ) ) {
|
if ( ! empty( $exif['ExposureTime'] ) ) {
|
||||||
|
$meta['shutter_speed'] = (string) $exif['ExposureTime'];
|
||||||
|
if ( is_scalar( $exif['ExposureTime'] ) ) {
|
||||||
$meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] );
|
$meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ( ! empty( $exif['Orientation'] ) ) {
|
if ( ! empty( $exif['Orientation'] ) ) {
|
||||||
$meta['orientation'] = $exif['Orientation'];
|
$meta['orientation'] = $exif['Orientation'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '5.9-alpha-52268';
|
$wp_version = '5.9-alpha-52269';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue