Media: Return WP_Error when cropping with bad input to avoid fatal.

This avoids an error on PHP 8 caused by calling `wp_imagecreatetruecolor()` with inputs that aren't numeric, or are less than 0.

Props hellofromtonya, Boniu91, metalandcoffee, SergeyBiryukov.
Fixes #51937.


git-svn-id: https://develop.svn.wordpress.org/trunk@49751 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Ian Dunn
2020-12-04 21:39:30 +00:00
parent 2b0e2d62a2
commit 8724f546c9
3 changed files with 117 additions and 8 deletions

View File

@@ -323,7 +323,13 @@ class WP_Image_Editor_GD extends WP_Image_Editor {
$dst_h = $src_h;
}
$dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
foreach ( array( $src_w, $src_h, $dst_w, $dst_h ) as $value ) {
if ( ! is_numeric( $value ) || (int) $value <= 0 ) {
return new WP_Error( 'image_crop_error', __( 'Image crop failed.' ), $this->file );
}
}
$dst = wp_imagecreatetruecolor( (int) $dst_w, (int) $dst_h );
if ( $src_abs ) {
$src_w -= $src_x;
@@ -334,7 +340,7 @@ class WP_Image_Editor_GD extends WP_Image_Editor {
imageantialias( $dst, true );
}
imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
imagecopyresampled( $dst, $this->image, 0, 0, (int) $src_x, (int) $src_y, (int) $dst_w, (int) $dst_h, (int) $src_w, (int) $src_h );
if ( is_gd_image( $dst ) ) {
imagedestroy( $this->image );

View File

@@ -3505,7 +3505,7 @@ function is_gd_image( $image ) {
*
* @param int $width Image width in pixels.
* @param int $height Image height in pixels.
* @return resource|GdImage The GD image resource or GdImage instance.
* @return resource|GdImage|false The GD image resource or GdImage instance on success. False on failure.
*/
function wp_imagecreatetruecolor( $width, $height ) {
$img = imagecreatetruecolor( $width, $height );

View File

@@ -405,25 +405,128 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase {
}
/**
* Test cropping an image
* Test cropping an image.
*
* @ticket 51937
*
* @dataProvider data_crop
*/
public function test_crop() {
public function test_crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
$file = DIR_TESTDATA . '/images/gradient-square.jpg';
$gd_image_editor = new WP_Image_Editor_GD( $file );
$gd_image_editor->load();
$gd_image_editor->crop( 0, 0, 50, 50 );
$gd_image_editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
$this->assertSame(
array(
'width' => 50,
'height' => 50,
'width' => (int) $src_w,
'height' => (int) $src_h,
),
$gd_image_editor->get_size()
);
}
public function data_crop() {
return array(
'src height and width must be greater than 0' => array(
'src_x' => 0,
'src_y' => 0,
'src_w' => 50,
'src_h' => 50,
),
'src height and width can be string but must be greater than 0' => array(
'src_x' => 10,
'src_y' => '10',
'src_w' => '50',
'src_h' => '50',
),
'dst height and width must be greater than 0' => array(
'src_x' => 10,
'src_y' => '10',
'src_w' => 150,
'src_h' => 150,
'dst_w' => 150,
'dst_h' => 150,
),
'dst height and width can be string but must be greater than 0' => array(
'src_x' => 10,
'src_y' => '10',
'src_w' => 150,
'src_h' => 150,
'dst_w' => '150',
'dst_h' => '150',
),
);
}
/**
* Test should return WP_Error when dimensions are not integer or are <= 0.
*
* @ticket 51937
*
* @dataProvider data_crop_invalid_dimensions
*/
public function test_crop_invalid_dimensions( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
$file = DIR_TESTDATA . '/images/gradient-square.jpg';
$gd_image_editor = new WP_Image_Editor_GD( $file );
$gd_image_editor->load();
$actual = $gd_image_editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
$this->assertInstanceOf( 'WP_Error', $actual );
$this->assertSame( 'image_crop_error', $actual->get_error_code() );
}
public function data_crop_invalid_dimensions() {
return array(
'src height must be greater than 0' => array(
'src_x' => 0,
'src_y' => 0,
'src_w' => 100,
'src_h' => 0,
),
'src width must be greater than 0' => array(
'src_x' => 10,
'src_y' => '10',
'src_w' => 0,
'src_h' => 100,
),
'src height must be numeric and greater than 0' => array(
'src_x' => 10,
'src_y' => '10',
'src_w' => 100,
'src_h' => 'NaN',
),
'dst height must be numeric and greater than 0' => array(
'src_x' => 0,
'src_y' => 0,
'src_w' => 100,
'src_h' => 50,
'dst_w' => '100',
'dst_h' => 'NaN',
),
'src and dst height and width must be greater than 0' => array(
'src_x' => 0,
'src_y' => 0,
'src_w' => 0,
'src_h' => 0,
'dst_w' => 0,
'dst_h' => 0,
),
'src and dst height and width can be string but must be greater than 0' => array(
'src_x' => 0,
'src_y' => 0,
'src_w' => '0',
'src_h' => '0',
'dst_w' => '0',
'dst_h' => '0',
),
);
}
/**
* Test rotating an image 180 deg
*/