From 9be394fe38cf6deaece315789156ce5ca3a2e2fc Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Jan 2026 20:07:10 +0100 Subject: [PATCH] Make wxXmlInitResourceModule() safer to use This function unconditionally added a new wxXmlResourceModule object to the modules list which could result in problems if it had been already initialized. Ensure that we do this only if necessary by calling the new function added to wxModule which checks if the module is already known and adds and initializes only this module if it is not. See #26111. Closes #26039. --- include/wx/module.h | 4 ++++ src/common/module.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/xrc/xmlres.cpp | 14 +++++++++++--- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/include/wx/module.h b/include/wx/module.h index 49e747043b..da8299d864 100644 --- a/include/wx/module.h +++ b/include/wx/module.h @@ -54,6 +54,10 @@ public: static void UnregisterModule(wxModule *module); + // Initialize the module with the given type information if it's not + // already initialized. This is for internal use only currently. + static void AddModuleIfNecessary(const wxClassInfo *classInfo); + protected: static wxModuleList ms_modules; diff --git a/src/common/module.cpp b/src/common/module.cpp index 22ca1e143a..dc4da410a9 100644 --- a/src/common/module.cpp +++ b/src/common/module.cpp @@ -18,6 +18,8 @@ #include "wx/log.h" #endif +#include + #define TRACE_MODULE wxT("module") wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject); @@ -148,6 +150,43 @@ bool wxModule::DoInitializeModule(wxModule *module, return true; } +void wxModule::AddModuleIfNecessary(const wxClassInfo *classInfo) +{ + wxCHECK_RET( classInfo, wxS("Valid class info must be provided") ); + wxCHECK_RET( classInfo->IsKindOf(wxCLASSINFO(wxModule)), + wxS("Class info must be for wxModule-derived class") ); + + const wxString className(classInfo->GetClassName()); + for ( wxModuleList::const_iterator it = ms_modules.begin(); + it != ms_modules.end(); + ++it ) + { + if ( (*it)->GetClassInfo()->GetClassName() == className ) + { + // Already initialized or at least registered and will be + // initialized later. + return; + } + } + + std::unique_ptr + module{static_cast(classInfo->CreateObject())}; + + // Do not call RegisterModule() here as it would add it to ms_modules which + // would result in it being added twice as DoInitializeModule() would do it + // too on success. + module->m_state = State_Registered; + + if ( !DoInitializeModule(module.get(), ms_modules) ) + { + // Error is already given by DoInitializeModule(). + return; + } + + // Module is now owned by ms_modules. + module.release(); +} + // Initialize user-defined modules bool wxModule::InitializeModules() { diff --git a/src/xrc/xmlres.cpp b/src/xrc/xmlres.cpp index 222bd0e94f..4d967d065b 100644 --- a/src/xrc/xmlres.cpp +++ b/src/xrc/xmlres.cpp @@ -3255,9 +3255,17 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxXmlResourceModule, wxModule); // then the built-in module system won't pick this one up. Add it manually. void wxXmlInitResourceModule() { - wxModule* module = new wxXmlResourceModule; - wxModule::RegisterModule(module); - wxModule::InitializeModules(); + // Only add the module if the module system is already initialized, + // otherwise it will be added automatically when it is done as it will be + // known to the module system at that time (this happens as soon as the + // code containing this function is loaded from a shared library and if + // this function is running, it must have been already loaded!). + if ( wxModule::AreInitialized() ) + { + // Still check that this module is not already registered, as could + // happen if this function is called multiple times, for example. + wxModule::AddModuleIfNecessary(wxCLASSINFO(wxXmlResourceModule)); + } } #endif // wxUSE_XRC