Make WordPress Core

Opened 4 years ago

Last modified 4 years ago

#51947 new defect (bug)

When Customizer `setup_theme` action fails during wp-settings.php, WordPress crashes due to missing global $wp_locale

Reported by: guss77's profile Guss77 Owned by:
Milestone: Future Release Priority: normal
Severity: major Version: 4.6
Component: Customize Keywords: needs-patch
Focuses: Cc:

Description

The wp-settings.php sets up the global $wp_locale (line 499 in WordPress 5.5.3) but before doing that it calls do_action( 'setup_theme' ); (line 478).

The problem is that WP_Customize_Manager::setup_theme() has several failure actions that call the class's wp_die() "wrapper" which - depending on the value of the messenger_channel might try to call wp_enqueue_scripts(), which will eventually call wp_localize_jquery_ui_datepicker() that expects $wp_locale to be already set. The result is a crash.

Here is one such stack trace:

PHP Fatal error:  Uncaught Error: Call to a member function is_rtl() on null in /var/www/html/wp-includes/script-loader.php:1684
Stack trace:
#0 /var/www/html/wp-includes/class-wp-hook.php(287): wp_localize_jquery_ui_datepicker('')
#1 /var/www/html/wp-includes/class-wp-hook.php(311): WP_Hook->apply_filters(NULL, Array)
#2 /var/www/html/wp-includes/plugin.php(478): WP_Hook->do_action(Array)
#3 /var/www/html/wp-includes/script-loader.php(2001): do_action('wp_enqueue_scri...')
#4 /var/www/html/wp-includes/class-wp-customize-manager.php(454): wp_enqueue_scripts()
#5 /var/www/html/wp-includes/class-wp-customize-manager.php(551): WP_Customize_Manager->wp_die(0, 'Non-existent ch...')
#6 /var/www/html/wp-includes/class-wp-hook.php(287): WP_Customize_Manager->setup_theme('')
#7 /var/www/html/wp-includes/class-wp-hook.php(311): WP_Hook->apply_filters(NULL, Array)
#8 /var/www/html/wp-includes/plugin.php(478): WP_Hook->do_action(Array)
#9 /var/www/html/wp-settings.php(478): do_action('setup_theme')
#10 /var/www/html/wp-config.php(97): req...
in /var/www/html/wp-includes/script-loader.php on line 1684, referer: https://somesite.com/

Moving the do_action( 'setup_theme' ); line down a few lines until after the local has been setup, and just before loading the active theme's function.php file (which is arguably where it was supposed to be in the first place) solves the problem.

Change History (7)

#1 @dlh
4 years ago

  • Keywords reporter-feedback added
  • Version 5.5.3 deleted

Thanks for the report, @Guss77!

Can you provide steps to replicate this behavior?

#2 @Guss77
4 years ago

For me it happens when the customizer is trying to output the "Non-existent changeset UUID" error message, and this happened on my multi-site with the MU Domain Mapping plugin when accessing the customizer in a site where the primary domain name is not a sub-domain of the multisite "DOMAIN_CURRENT_SITE".

#3 follow-up: @dlh
4 years ago

In my testing so far, I'm unable to replicate that fatal error. The script exits as expected.

wp_localize_jquery_ui_datepicker() won't attempt to use the $wp_locale global unless the jquery-ui-datepicker script is enqueued — see https://github.com/WordPress/wordpress-develop/blob/901909bf2cc79333d424628cef2064770b4b839b/src/wp-includes/script-loader.php#L1666-L1671.

Is a plugin enqueuing the datepicker? If so, when in the bootstrap cycle is it being enqueued, and how?

#4 in reply to: ↑ 3 @Guss77
4 years ago

Replying to dlh:

Is a plugin enqueuing the datepicker? If so, when in the bootstrap cycle is it being enqueued, and how?

very likely - I have several plugins installed that call wp_enqueue_script('jquery-ui-datepicker') or wp_register_script() with jquery-ui-datepicker as a dependency.

  • WordPress File Upload: calls wp_enqueue_script('jquery-ui-datepicker') from admin_print_scripts hook.
  • Contact Form 7: calls wp_enqueue_script('jquery-ui-datepicker') from the wp_enqueue_scripts hook.
  • Woo Order Export Lite: calls wp_enqueue_script('jquery-ui-datepicker') from admin_enqueue_scripts hook.

I think maybe the Contact Form 7 plugin is the issue, but I can list the plugins calling wp_register_script() if that is not it.

#5 @dlh
4 years ago

  • Keywords needs-patch added; reporter-feedback removed
  • Milestone changed from Awaiting Review to 5.7
  • Version set to 4.6

No need for the list of plugins, @Guss77. I can replicate simply by enqueuing the datepicker on wp_enqueue_scripts, since WP_Customize_Manager invokes it before exiting: https://github.com/WordPress/wordpress-develop/blob/668581d0f3be00c0babe6929f97ecce654507843/src/wp-includes/class-wp-customize-manager.php#L454

Moving the timing of setup_theme is going to be a non-starter for backwards-compatibility concerns, I suspect, but the I18N or theme component maintainers might have ideas for doing so. Adding safety checks to wp_localize_jquery_ui_datepicker() might be a less-risky approach. Let's see whether we can work something out in 5.7.

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


4 years ago

#7 @johnbillion
4 years ago

  • Milestone changed from 5.7 to Future Release

Bumping, pending ideas on how to fix this and a patch.

Note: See TracTickets for help on using tickets.