Skip to content

WP_Site::get_instance() fatals when the cached value is not an object - #13270

Open
josephscott wants to merge 1 commit into
WordPress:trunkfrom
josephscott:65962/wp-site-get-instance-cache-check
Open

WP_Site::get_instance() fatals when the cached value is not an object#13270
josephscott wants to merge 1 commit into
WordPress:trunkfrom
josephscott:65962/wp-site-get-instance-cache-check

Conversation

@josephscott

Copy link
Copy Markdown
Contributor

See https://core.trac.wordpress.org/ticket/65962

This is similar to protections for WP_Post that was added in 578d09b by @westonruter

AI assistance: No


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

$_site = wp_cache_get( $site_id, 'sites' );

if ( false === $_site ) {
if ( ! is_object( $_site ) && ! is_numeric( $_site ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, this fixes a PHPStan error:

  192    Parameter #1 $site of class WP_Site constructor expects object, mixed given.                
         🪪  argument.type                                                                           
         at src/wp-includes/class-wp-site.php:192   

But it could be hardened. What if some arbitrary object is returned that isn't a WP_Site?

Suggested change
if ( ! is_object( $_site ) && ! is_numeric( $_site ) ) {
// A cached -1 records a previous lookup that found nothing. Anything else that is not a site object is treated as a cache miss.
if (
( ! is_object( $_site ) || ! isset( $_site->blog_id ) )
&&
! is_numeric( $_site )
) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change I did in 578d09b probably should be updated to apply this as well:

- if ( ! ( $_post instanceof stdClass ) && ! ( $_post instanceof WP_Post ) ) {
+ if ( ! is_object( $_post ) || ! isset( $_post->ID ) ) {

if ( ! is_object( $_site ) && ! is_numeric( $_site ) ) {
$_site = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->blogs} WHERE blog_id = %d LIMIT 1", $site_id ) );

if ( empty( $_site ) || is_wp_error( $_site ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that wpdb::get_row() can never return WP_Error, so this is dead code. Now, maybe it is used by some db.php drop-in that does return WP_Error for a get_row() call, but that would be highly problematic for other calls elsewhere in core, where an object is assumed to be a valid DB row.

Suggested change
if ( empty( $_site ) || is_wp_error( $_site ) ) {
if ( empty( $_site ) ) {

Not necessary here. Just something I noticed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants