From b3c93f502e79cae3b07a3b7063f37193edcde3f3 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 30 Mar 2026 00:17:42 +0000 Subject: [PATCH] Media: Guard against `false` return values from `wp_get_attachment_image_src()` and `wp_getimagesize()`. * Add `is_array()` checks before accessing return values from `wp_get_attachment_image_src()` in `get_oembed_response_data_rich()`, `wp_playlist_shortcode()`, and `wp_prepare_attachment_for_js()`. * Guard `wp_getimagesize()` calls within `wp_get_attachment_image_src()` itself. * Ensure `wp_get_attachment_image_src()` always returns the expected `array{0: string, 1: int, 2: int, 3: bool}` type or `false` by normalizing the filter result with explicit type casting and default values. * Add `@phpstan-return` annotations to both `wp_get_attachment_image_src()` and `wp_getimagesize()` for the specific array shapes. Developed in https://github.com/WordPress/wordpress-develop/pull/11073 Props hbhalodia, westonruter, mukesh27, edent, ozgursar, roshniahuja14. Fixes #64742. Built from https://develop.svn.wordpress.org/trunk@62176 git-svn-id: http://core.svn.wordpress.org/trunk@61458 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/embed.php | 11 ++++--- wp-includes/media.php | 71 ++++++++++++++++++++++++++++++++++------- wp-includes/version.php | 2 +- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/wp-includes/embed.php b/wp-includes/embed.php index dd21b6cf22..3fb8968c7c 100644 --- a/wp-includes/embed.php +++ b/wp-includes/embed.php @@ -739,10 +739,13 @@ function get_oembed_response_data_rich( $data, $post, $width, $height ) { } if ( $thumbnail_id ) { - list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 0 ) ); - $data['thumbnail_url'] = $thumbnail_url; - $data['thumbnail_width'] = $thumbnail_width; - $data['thumbnail_height'] = $thumbnail_height; + $thumbnail_src = wp_get_attachment_image_src( $thumbnail_id, array( $width, 0 ) ); + + if ( is_array( $thumbnail_src ) ) { + $data['thumbnail_url'] = $thumbnail_src[0]; + $data['thumbnail_width'] = $thumbnail_src[1]; + $data['thumbnail_height'] = $thumbnail_src[2]; + } } return $data; diff --git a/wp-includes/media.php b/wp-includes/media.php index 7ff250413a..5277ec351b 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -972,12 +972,15 @@ function wp_get_registered_image_subsizes() { * @type int $2 Image height in pixels. * @type bool $3 Whether the image is a resized image. * } + * @phpstan-return array{ 0: string, 1: int, 2: int, 3: bool }|false */ function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) { // Get a thumbnail or intermediate image if there is one. $image = image_downsize( $attachment_id, $size ); if ( ! $image ) { - $src = false; + $src = false; + $width = 0; + $height = 0; if ( $icon ) { $src = wp_mime_type_icon( $attachment_id, '.svg' ); @@ -988,7 +991,11 @@ function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon $src_file = $icon_dir . '/' . wp_basename( $src ); - list( $width, $height ) = wp_getimagesize( $src_file ); + $image_size = wp_getimagesize( $src_file ); + if ( is_array( $image_size ) ) { + $width = $image_size[0]; + $height = $image_size[1]; + } $ext = strtolower( substr( $src_file, -4 ) ); @@ -997,7 +1004,11 @@ function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon $width = 48; $height = 64; } else { - list( $width, $height ) = wp_getimagesize( $src_file ); + $image_size = wp_getimagesize( $src_file ); + if ( is_array( $image_size ) ) { + $width = $image_size[0]; + $height = $image_size[1]; + } } } } @@ -1024,7 +1035,16 @@ function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon * an array of width and height values in pixels (in that order). * @param bool $icon Whether the image should be treated as an icon. */ - return apply_filters( 'wp_get_attachment_image_src', $image, $attachment_id, $size, $icon ); + $source = apply_filters( 'wp_get_attachment_image_src', $image, $attachment_id, $size, $icon ); + if ( is_array( $source ) && isset( $source[0] ) && is_string( $source[0] ) ) { + return array( + $source[0], + (int) ( $source[1] ?? 0 ), + (int) ( $source[2] ?? 0 ), + (bool) ( $source[3] ?? false ), + ); + } + return false; } /** @@ -3230,10 +3250,23 @@ function wp_playlist_shortcode( $attr ) { if ( $atts['images'] ) { $thumb_id = get_post_thumbnail_id( $attachment->ID ); if ( ! empty( $thumb_id ) ) { - list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'full' ); - $track['image'] = compact( 'src', 'width', 'height' ); - list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'thumbnail' ); - $track['thumb'] = compact( 'src', 'width', 'height' ); + $image_src_full = wp_get_attachment_image_src( $thumb_id, 'full' ); + if ( is_array( $image_src_full ) ) { + $track['image'] = array( + 'src' => $image_src_full[0], + 'width' => $image_src_full[1], + 'height' => $image_src_full[2], + ); + } + + $image_src_thumb = wp_get_attachment_image_src( $thumb_id, 'thumbnail' ); + if ( is_array( $image_src_thumb ) ) { + $track['thumb'] = array( + 'src' => $image_src_thumb[0], + 'width' => $image_src_thumb[1], + 'height' => $image_src_thumb[2], + ); + } } else { $src = wp_mime_type_icon( $attachment->ID, '.svg' ); $width = 48; @@ -4711,10 +4744,23 @@ function wp_prepare_attachment_for_js( $attachment ) { $id = get_post_thumbnail_id( $attachment->ID ); if ( ! empty( $id ) ) { - list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'full' ); - $response['image'] = compact( 'src', 'width', 'height' ); - list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'thumbnail' ); - $response['thumb'] = compact( 'src', 'width', 'height' ); + $response_image_full = wp_get_attachment_image_src( $id, 'full' ); + if ( is_array( $response_image_full ) ) { + $response['image'] = array( + 'src' => $response_image_full[0], + 'width' => $response_image_full[1], + 'height' => $response_image_full[2], + ); + } + + $response_image_thumb = wp_get_attachment_image_src( $id, 'thumbnail' ); + if ( is_array( $response_image_thumb ) ) { + $response['thumb'] = array( + 'src' => $response_image_thumb[0], + 'width' => $response_image_thumb[1], + 'height' => $response_image_thumb[2], + ); + } } else { $src = wp_mime_type_icon( $attachment->ID, '.svg' ); $width = 48; @@ -5724,6 +5770,7 @@ function wp_show_heic_upload_error( $plupload_settings ) { * @param string $filename The file path. * @param array $image_info Optional. Extended image information (passed by reference). * @return array|false Array of image information or false on failure. + * @phpstan-return array{ 0: int, 1: int, 2: int, 3: string, mime: string, bits?: int, channels?: int }|false */ function wp_getimagesize( $filename, ?array &$image_info = null ) { // Don't silence errors when in debug mode, unless running unit tests. diff --git a/wp-includes/version.php b/wp-includes/version.php index 441f323390..a2dc443d5b 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '7.1-alpha-62175'; +$wp_version = '7.1-alpha-62176'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.