Skip to content

[core] Fix plugin lookup when Root.PluginPath has multiple directories - #23796

Open
JainAyush-01 wants to merge 1 commit into
root-project:masterfrom
JainAyush-01:fix/23536-root-plugin-path
Open

JainAyush-01 wants to merge 1 commit into
root-project:masterfrom
JainAyush-01:fix/23536-root-plugin-path

Conversation

@JainAyush-01

Copy link
Copy Markdown

This Pull request:

Fixes an in-place string mutation bug in TPluginManager::LoadHandlersFromPluginDirs that breaks plugin discovery when Root.PluginPath (or ROOT_PLUGIN_PATH) contains multiple colon-separated directories.

Changes or fixes:

Root Cause:

In commit e60640c (#18859), gSystem->ConcatFileName was replaced with gSystem->PrependPathName. Unlike ConcatFileName which returned a new heap-allocated string without modifying the input, PrependPathName(const char *dir, TString &name) modifies name in place.

In TPluginManager::LoadHandlersFromPluginDirs(const char *base):

TString sbase = base;
...
for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
   ...
   if (!skip) {
      if (sbase != "") {
         const char *p = gSystem->PrependPathName(d, sbase);
         LoadHandlerMacros(p);
      }
   }
}

Because sbase was passed directly to PrependPathName without copying to a temporary variable:

  • On iteration 0 (dir0 = "/custom/plugins"): sbase was mutated from "TArchiveFile" to "/custom/plugins/TArchiveFile".
  • On iteration 1 (dir1 = "$ROOTSYS/etc/plugins"): PrependPathName prepended dir1 to the already mutated sbase, resulting in "$ROOTSYS/etc/plugins//custom/plugins/TArchiveFile".

As a result, whenever a user or experiment environment (e.g. ALICE O2 / JAliEn) prepended a custom directory to Root.PluginPath, all subsequent directories—including ROOT's own built-in plugins in $ROOTSYS/etc/plugins—failed to load.

Fix:

Copy sbase to a temporary TString temp = sbase; inside the loop before calling PrependPathName(d, temp), matching the pattern already used in the else branch (lines 545–546) and throughout TPluginManager.cxx.

Testing:

  • Added GoogleTest regression test TEST(TPluginManager, MultiDirectoryPluginPath) in core/base/test/TPluginManagerTests.cxx.
  • Verified that both custom plugins in a prepended directory and built-in plugins in subsequent directories are resolved properly.
  • Ran test via ctest -R CorePluginManagerTests: 100% passed (0.26s).

Checklist:

  • tested changes locally
  • updated the docs (if necessary)

This PR fixes #23536

When Root.PluginPath (or ROOT_PLUGIN_PATH) contains multiple colon-separated
directories, TPluginManager::LoadHandlersFromPluginDirs loops over each
directory to load handler macros for the requested base class.

In commit e60640c (root-project#18859), ConcatFileName was replaced by PrependPathName.
Unlike ConcatFileName which returned a new heap-allocated string,
PrependPathName modifies its second parameter in-place. Because `sbase`
was passed directly:
    const char *p = gSystem->PrependPathName(d, sbase);
the variable `sbase` was mutated in-place across iterations (e.g., from
"TArchiveFile" to "/dir1/TArchiveFile", then to "/dir2//dir1/TArchiveFile").
Consequently, subsequent search directories received a mangled path and
ROOT could not find its own built-in plugins whenever a custom plugin
directory was prepended.

Fix this by copying `sbase` to a temporary `TString temp = sbase;` on each
iteration, matching the pattern used in the rest of TPluginManager.cxx.

Fixes root-project#23536. Added regression test in core/base/test/TPluginManagerTests.cxx.

This branch has not been deployed

No deployments
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.

ROOT_PLUGIN_PATH is handled incorrectly

1 participant