From d016c90486a42e006ab2f7237e85af279a7e705a Mon Sep 17 00:00:00 2001 From: bneradt Date: Wed, 2 Sep 2026 15:50:44 -0500 Subject: [PATCH] Fix use-after-move in ConfigRegistry::do_register std::unordered_map::emplace may construct its node before discovering the key is already present, consuming the moved-from Entry even though nothing was inserted. The duplicate-registration warning then read plugin_name out of that gutted Entry and reported the incoming owner as "core". try_emplace leaves the argument untouched when the key exists, so the warning can name the registration it rejected. The read after the move came in with #13146, so the clang-analyzer job's Clang-Tidy stage (bugprone-use-after-move) now fails on master. Co-Authored-By: Claude Opus 5 --- src/mgmt/config/ConfigRegistry.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mgmt/config/ConfigRegistry.cc b/src/mgmt/config/ConfigRegistry.cc index eb8fc3926ae..49330d301b6 100644 --- a/src/mgmt/config/ConfigRegistry.cc +++ b/src/mgmt/config/ConfigRegistry.cc @@ -217,7 +217,7 @@ ConfigRegistry::do_register(Entry entry) entry.trigger_records.size()); std::unique_lock lock(_mutex); - auto [it, inserted] = _entries.emplace(entry.key, std::move(entry)); + auto [it, inserted] = _entries.try_emplace(entry.key, std::move(entry)); if (inserted) { setup_triggers(it->second); @@ -238,9 +238,7 @@ ConfigRegistry::do_register(Entry entry) } else { auto const &existing = it->second; char const *existing_owner = existing.plugin_name.empty() ? "core" : existing.plugin_name.c_str(); - char const *incoming_owner = entry.plugin_name.empty() ? "core" : entry.plugin_name.c_str(); - Warning("Config '%s' already registered by %s; ignoring registration from %s", it->first.c_str(), existing_owner, - incoming_owner); + Warning("Config '%s' already registered by %s; ignoring registration from %s", it->first.c_str(), existing_owner, owner_str); } return inserted;