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.
This commit is contained in:
Vadim Zeitlin
2026-01-25 01:41:54 +01:00
parent d662d5f6a0
commit 9be394fe38
3 changed files with 54 additions and 3 deletions
+4
View File
@@ -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;
+39
View File
@@ -18,6 +18,8 @@
#include "wx/log.h"
#endif
#include <memory>
#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<wxModule>
module{static_cast<wxModule*>(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()
{
+11 -3
View File
@@ -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