Make WordPress Core

Opened 8 weeks ago

Last modified 3 days ago

#64742 reopened defect (bug)

PHP 8.5: Incorrect array access in `wp_get_attachment_image_src`

Reported by: edent's profile edent Owned by: westonruter's profile westonruter
Milestone: 7.0.1 Priority: normal
Severity: minor Version: 4.4
Component: General Keywords: good-first-bug has-patch has-unit-tests fixed-major dev-feedback
Focuses: php-compatibility Cc:

Description

Similar to #64295 and #63977

Warning at /wp-json/oembed/1.0/embed?url=https%3A%2F%2Fshkspr.mobi%2Fblog%2Fabout%2F&format=xml: [2] Cannot use bool as array in /wp-includes/embed.php on line 742

From https://github.com/WordPress/wordpress-develop/blob/f041be2a79eb9694217d716da3bf6d53f63a2173/src/wp-includes/embed.php#L742 :

function get_oembed_response_data_rich( $data, $post, $width, $height ) {
   […]
   list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 0 ) );

wp_get_attachment_image_src() returns array|false - but this only expects an array.

Change History (15)

#1 @westonruter
8 weeks ago

  • Keywords good-first-bug added
  • Milestone changed from Awaiting Review to 7.0
  • Version changed from 6.9.1 to 4.4

This ticket was mentioned in PR #11073 on WordPress/wordpress-develop by @hbhalodia.


8 weeks ago
#2

  • Keywords has-patch added

Trac ticket: https://core.trac.wordpress.org/ticket/64742

## Use of AI Tools

  • NA

This ticket was mentioned in PR #11213 on WordPress/wordpress-develop by @ant1busted.


6 weeks ago
#3

When attachment is missing wp_get_attachment_image_src returns false, which triggers a warning in PHP8.5 because il tries to use list() to destructure the array.
I simply added a check to make sure we are dealing with an array before destructuring it.

Trac ticket: https://core.trac.wordpress.org/ticket/64742

## Use of AI Tools
I code using Cursor. I coded the fix myself but asked cursor to make sure this would not create any side-effects.

---

@mukesh27 commented on PR #11213:


6 weeks ago
#4

Thanks for the PR!

PR #11073 was already opened about two weeks ago and follows the same approach. I’m closing this as a duplicate for now. Feel free to reopen it if you believe your approach is different from that one. Thanks!

#5 @desrosj
5 weeks ago

  • Milestone changed from 7.0 to 7.0.1

This still needs some more attention. Punting to 7.0.1.

This ticket was mentioned in Slack in #core-test by ozgur_sar. View the logs.


4 weeks ago

#7 @ozgursar
4 weeks ago

Patch Testing Report

Patch Tested: https://github.com/WordPress/wordpress-develop/pull/11073

Environment

  • WordPress: 7.0-RC1-62111-src
  • PHP: 8.5.4
  • Server: nginx/1.29.4
  • Database: mysqli (Server: 8.4.7 / Client: mysqlnd 8.5.4)
  • Browser: Chrome 145.0.0.0
  • OS: macOS
  • Theme: Twenty Twenty-Five 1.4
  • MU Plugins: None activated
  • Plugins:
    • Code Snippets 3.9.5
    • Test Reports 1.2.1

Steps taken

  1. Create a new post and add a featured image to it
  2. Edit that post and note the post id from the URL (e.g /wp-admin/post.php?post=42&action=edit)
  3. To simulate the non-existing thumbnail scenario add the following snippet to active theme's functions.php or via Code Snippets plugin to set the featured image to a non existing media id.
add_action( 'init', function() {
    // Replace 42 with your your post ID that you noted in Step 2.
    // 999999 is the non-existing media ID
    update_post_meta( 42, '_thumbnail_id', 999999 );
} );
  1. Visit the following URL, replacing the YOUR_POST_URL with your test post's actual URL. Example:
http://localhost:8889/wp-json/oembed/1.0/embed?url=YOUR_POST_URL/&format=xml

  1. Observe the PHP Warning: Cannot use bool as array in /var/www/src/wp-includes/embed.php on line 742 error in debug.log as well as in the browser.
  2. Apply the patch and repeat the steps 4-5.
  3. ✅ Patch is solving the problem

Expected result

  • A valid XML oEmbed response is returned even when the thumbnail doesn't exist.

Screenshots/Screencast with results

Before
https://i.imgur.com/nU1z2No.png

After
https://i.imgur.com/5yz0mQd.png

@westonruter commented on PR #11073:


4 weeks ago
#8

@hbhalodia I made some more tweaks upon reviewing. Please review.

@hbhalodia commented on PR #11073:


4 weeks ago
#9

Thanks @westonruter, Looks good.

Checked on removed redundant type coersion, Updated the return type with exact array shape. We are in good shape to go ahead with the PR.

This ticket was mentioned in PR #11365 on WordPress/wordpress-develop by @roshniahuja14.


4 weeks ago
#10

  • Keywords has-unit-tests added

## Summary

  • Fixes PHP 8.5 warning when list() is used to destructure false returned by wp_get_attachment_image_src()
  • Adds is_array() guards in embed.php (get_oembed_response_data_rich), and media.php (wp_get_attachment_image_src, wp_playlist_shortcode, wp_prepare_attachment_for_js)
  • Adds unit tests for invalid thumbnail scenarios

## Trac Ticket

https://core.trac.wordpress.org/ticket/64742

## Test Plan

  • [x] PHPUnit tests pass (430 tests in Media + oEmbed suites)
  • [x] Manual test: set _thumbnail_id to a non-existent ID, visit oEmbed endpoint — no warnings, no null thumbnail keys

#11 @roshniahuja14
4 weeks ago

I've submitted a pull request for this issue: https://github.com/WordPress/wordpress-develop/pull/11365

Changes:

  • Added is_array() guards before list() destructuring of wp_get_attachment_image_src() return value in get_oembed_response_data_rich(), wp_playlist_shortcode(), and wp_prepare_attachment_for_js()
  • Guarded wp_getimagesize() return inside wp_get_attachment_image_src() itself
  • Added unit tests covering invalid thumbnail ID scenarios

Testing:

  • All existing PHPUnit tests pass (430 tests in Media + oEmbed suites)
  • Manually verified: set _thumbnail_id to a non-existent ID, visited the oEmbed endpoint — no PHP warnings, thumbnail keys are cleanly omitted from the response

@westonruter commented on PR #11365:


4 weeks ago
#12

Thanks for the PR, but there is an existing on linked on the ticket which is nearing merge. See https://github.com/WordPress/wordpress-develop/pull/11073.

#13 @westonruter
4 weeks ago

  • Owner set to westonruter
  • Resolution set to fixed
  • Status changed from new to closed

In 62176:

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.

#14 @westonruter
4 weeks ago

  • Keywords fixed-major dev-feedback added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Re-opening for 7.0.1 backport consideration.

This ticket was mentioned in PR #11613 on WordPress/wordpress-develop by @dhrupo.


3 days ago
#15

## Summary
Guard the icon fallback path in wp_get_attachment_image_src() when wp_getimagesize() cannot read the icon file.

## Problem
When wp_get_attachment_image_src() falls back to a mime type icon, it assumes wp_getimagesize() returns an array and immediately reads width and height from it. If the icon file cannot be read, PHP 8.5 surfaces incorrect array access on that falsey return value.

## Solution
Store the result of wp_getimagesize() first and only read width and height when it returns an array. This preserves the existing false return behavior when the icon dimensions cannot be determined.

## Testing
Added a PHPUnit regression test that forces the mime type icon path to point at a missing icon file and verifies wp_get_attachment_image_src() returns false cleanly.

Verified in the configured local wordpress-develop environment with:

  • node ./tools/local-env/scripts/docker.js exec --user wp_php php ./vendor/bin/phpunit --filter test_wp_get_attachment_image_src_with_icon_when_icon_file_size_cannot_be_read tests/phpunit/tests/media.php
  • node ./tools/local-env/scripts/docker.js exec --user wp_php php ./vendor/bin/phpunit --filter 'test_wp_get_attachment_image_(url|src_with_icon_when_icon_file_size_cannot_be_read)' tests/phpunit/tests/media.php
Note: See TracTickets for help on using tickets.