Make WordPress Core

Opened 5 months ago

Last modified 4 months ago

#63730 new defect (bug)

get_blogs_of_user running on single install and crashes

Reported by: keffr3n's profile Keffr3n Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.8.2
Component: General Keywords: reporter-feedback has-patch
Focuses: Cc:

Description

Query Monitor crashes on 6.8.2, but works on 6.7.1

pinpointed to get_blogs_of_user()

I get this messge: [⚠️ WARNING] Blog object has empty blog_id.
Flsh install, no plugins active except query-monitor.

<?php
add_action('init', function() {
    if ( ! is_admin() || ! current_user_can('administrator') ) return;

    $user_id = get_current_user_id();

    error_log("[DEBUG] Testing get_blogs_of_user() for user_id $user_id");

    try {
        $blogs = get_blogs_of_user($user_id);

        // If we get this far, log the result
        error_log("[DEBUG] get_blogs_of_user() returned: " . print_r($blogs, true));

        // Extra: Check for empty meta key access
        foreach ( $blogs as $blog ) {
            if ( empty($blog->blog_id) ) {
                error_log("[⚠️ WARNING] Blog object has empty blog_id: " . print_r($blog, true));
            }
        }
    } catch (Throwable $e) {
        error_log("[ERROR] Exception from get_blogs_of_user(): " . $e->getMessage());
    }
});

Since your trace ends in a call to abs() → absint() → get_metadata_raw(), that means a non-numeric value is being passed to abs(), likely from malformed metadata.

If one of those keys is non-numeric or weirdly cast, it triggers:

absint( $meta_id ) → abs( $non_number ) → Fatal error
So the error isn't from a specific meta key, but from calling get_metadata() with an empty key, which causes WordPress to do something unsafe under certain plugin/plugin-free conditions.

Change History (3)

#1 @abcd95
5 months ago

  • Keywords needs-testing removed

Reproduction Report

Description

This report validates that the issue can be reproduced.

The function get_blogs_of_user() incorrectly returns an array with an stdClass object that is missing the blog_id property. Downstream code expects a valid blog_id.

Environment

  • WordPress: 6.9-alpha-60093-src
  • PHP: 8.2.25
  • Server: nginx/1.27.2
  • Database: mysqli (Server: 8.4.4 / Client: mysqlnd 8.2.25)
  • Browser: Chrome 138.0.0.0
  • OS: macOS
  • Theme: Twenty Twenty-Five 1.3
  • MU Plugins: None activated
  • Plugins:
    • Query Monitor 3.18.0

Reproduction steps

  • Spin up a single-site instance (no multisite enabled).
  • Activate Query Monitor ( or anything that uses blog_id later)
  • Add the test code snippet from the ticket to hook into init and call get_blogs_of_user() for the current user.
  • Make sure the debugging is enabled
  • Visit any admin page to trigger the code.
  • Check the debug output

Actual Results

✅ Error condition occurs (reproduced).

Additional Notes

Debug logs confirm the blog_id is missing from the returned object -

[DEBUG] get_blogs_of_user() returned: Array
(
    [1] => stdClass Object
        (
            [userblog_id] => 1
            [blogname] => wordpress-develop
            [domain] =>
            [path] =>
            [site_id] => 1
            [siteurl] => http://localhost:8889
            [archived] => 0
            [spam] => 0
            [deleted] => 0
            // Missing 'blog_id'
        )
)

Supplemental Artifacts

Full debug output - screenshot

#2 @johnbillion
5 months ago

  • Keywords reporter-feedback added

What's the relationship between this issue and Query Monitor?

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


4 months ago
#3

  • Keywords has-patch added

Summary
Fixed a backward compatibility issue in WordPress core where get_blogs_of_user() function returns objects missing the blog_id property on single-site installations.

Problem

  • On single-site WordPress installs, get_blogs_of_user() returns stdClass objects without the blog_id property
  • This causes downstream code to break when expecting a valid blog_id (e.g., absint() calls with undefined properties)
  • The issue affects core WordPress functions and plugins that rely on the blog_id property being presen

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

Note: See TracTickets for help on using tickets.