[wp-trac] [WordPress Trac] #50228: Plugins can inadvertently trigger `wp_die()` infinite loop during site creation

WordPress Trac noreply at wordpress.org
Fri May 22 21:11:05 UTC 2020


#50228: Plugins can inadvertently trigger `wp_die()` infinite loop during site
creation
--------------------------------+------------------------------
 Reporter:  iandunn             |       Owner:  (none)
     Type:  defect (bug)        |      Status:  new
 Priority:  normal              |   Milestone:  Awaiting Review
Component:  Networks and Sites  |     Version:
 Severity:  normal              |  Resolution:
 Keywords:                      |     Focuses:
--------------------------------+------------------------------
Changes (by iandunn):

 * focuses:  multisite =>
 * component:  Upgrade/Install => Networks and Sites


Old description:

> ==== Problem
>
> This is one example of an execution path that leads to an infinite loop,
> but there are probably several others. It can happen to any callback that
> tries to query a new site's tables after the `wp_insert_site` action, and
> before the `make_db_current_silent()` call inside `wp_initialize_site()`.
>
> 1. Creating a site in the UI or programatically calls eventually
> `wp_initialize_site()`
> 1. That calls `switch_to_blog()`
> 1. A plugin could hook into the `switch_blog()` action, and call
> `get_locale()`.
> 1. That calls `get_option()`, which will trigger a MySQL error, because
> the tables don't exist.
> 1. `wpdb->print_error( )` calls `_default_wp_die_handler()`
> 1. That calls `get_language_attributes()`, which calls `get_option()`
> 1. The process repeats until PHP gives up.
>
> > ( ! ) Fatal error: Uncaught Error: Maximum function nesting level of
> '256' reached, aborting! in wp-includes/class-wp-hook.php on line 196
>
> It's not obvious to plugin developers that this kind of thing can happen,
> so I think Core should handle it gracefully.
>
> Related: #49263
>
> ==== Potential solutions
>
> 1. `wp_die()` coule call a new `_installing_wp_die_handler()` when
> `is_installing()` is `true`. This could be a minimal version of
> `_default_wp_die_handler()`, where no database queries are
> made.[[br]][[br]]
> 1. `_default_wp_die_handler()` could avoid calling
> `get_language_attributes()` when  `is_installing()` is
> `true`.[[br]][[br]]
> 1. Something else?

New description:

 ==== Problem

 This is one example of an execution path that leads to an infinite loop,
 but there are probably several others. It can happen to any callback that
 tries to query a new site's tables after the `wp_insert_site` action, and
 before the `make_db_current_silent()` call inside `wp_initialize_site()`.

 1. Creating a new site in a Multisite network will eventually call
 `wp_initialize_site()`
 1. That calls `switch_to_blog()`
 1. A plugin could hook into the `switch_blog()` action, and call
 `get_locale()`.
 1. That calls `get_option()`, which will trigger a MySQL error, because
 the tables don't exist.
 1. `wpdb->print_error( )` calls `_default_wp_die_handler()`
 1. That calls `get_language_attributes()`, which calls `get_option()`
 1. The process repeats until PHP gives up.

 > ( ! ) Fatal error: Uncaught Error: Maximum function nesting level of
 '256' reached, aborting! in wp-includes/class-wp-hook.php on line 196

 It's not obvious to plugin developers that this kind of thing can happen,
 so I think Core should handle it gracefully.

 Related: #49263

 ==== Potential solutions

 1. `wp_die()` coule call a new `_installing_wp_die_handler()` when
 `is_installing()` is `true`. This could be a minimal version of
 `_default_wp_die_handler()`, where no database queries are
 made.[[br]][[br]]
 1. `_default_wp_die_handler()` could avoid calling
 `get_language_attributes()` when  `is_installing()` is `true`.[[br]][[br]]
 1. Something else?

--

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/50228#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list