[wp-trac] [WordPress Trac] #42670: Symlinked plugin makes plugin_basename function return wrong basename

WordPress Trac noreply at wordpress.org
Tue Aug 1 17:09:40 UTC 2023


#42670: Symlinked plugin makes plugin_basename function return wrong basename
----------------------------------------------------+---------------------
 Reporter:  sergiienko                              |       Owner:  (none)
     Type:  defect (bug)                            |      Status:  new
 Priority:  normal                                  |   Milestone:  6.4
Component:  Plugins                                 |     Version:  4.9
 Severity:  normal                                  |  Resolution:
 Keywords:  has-unit-tests has-patch needs-testing  |     Focuses:
----------------------------------------------------+---------------------

Comment (by brianhenryie):

 After I posted the repo above to reproduce the issue and verify the patch,
 @ironprogrammer and I discovered another related bug that should be fixed
 at the same time: my patch was written for an environment where there is a
 symlink inside a symlink (/wordpress/wp-content -> /wp-content, and /wp-
 content/plugins/example-plugin -> /). Where there is only one symlink
 (wordpress/wp-content/plugins -> .) the issue remains.

 I'm posting notes from the Slack thread here:

 ----

 So...
 [`wp_register_plugin_realpath()`](https://github.com/WordPress/WordPress/blob/9e0f2faa28f1aa04a69e0b4eaa410a38adcd2e1e
 /wp-includes/plugin.php#L819-L821) doesn't record the plugin realpath to
 `$wp_plugin_paths` if its calculated `realpath()` isn't any different to
 the `WP_PLUGIN_DIR` subdirectory path.

 Then when `$wp_plugin_paths` is looped over in `plugin_basename()`, where
 the "fix" is, the only entry is the only symlinked plugin, i.e. a-wp-
 trac-42670 in the project root, which then matches for every plugin
 queried in `plugin_basename()`.

 The bug can be fixed by removing the condition on whether the plugins'
 paths are recorded.

 Ideally `$wp_plugin_paths` would only be populated when there is one or
 more symlinked plugins, but we can't know this until looking at each one.

 Something like this could be used to empty the array afterwards in times
 when it's not needed:

 {{{#!php
 <?php
 add_action( 'plugins_loaded', function() {
         global $wp_plugin_paths;

         foreach ( $wp_plugin_paths as $dir => $realdir ) {
                 if( $dir !== $realdir ) {
                         return;
                 }
         }

         $wp_plugin_paths = array();
 }, 0);
 }}}

 ----

 Reflecting on that, the minimum addition to the patch should be:

 In `wp-includes/plugin.php:819` change:

 {{{#!php
 <?php
 if ( $plugin_path !== $plugin_realpath ) {
   $wp_plugin_paths[ $plugin_path ] = $plugin_realpath;
 }
 }}}

 to:

 {{{#!php
 <?php
 $wp_plugin_paths[ $plugin_path ] = $plugin_realpath;
 }}}


 The `plugins_loaded` code above might be best omitted for clarity. The
 performance impact here is how many times the sorted `global
 $wp_plugin_paths` array, whose length will be the number of plugins
 installed, is traversed by `plugin_basename()` (an admittedly popular
 function).

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


More information about the wp-trac mailing list