diff options
author | Attila Molnar <attilamolnar@hush.com> | 2014-01-05 13:47:28 +0100 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2014-01-05 13:47:28 +0100 |
commit | 7ce26772d93115e7c0a2644007351b57030710e6 (patch) | |
tree | 83122fd465f977b8f0d02f8d9a8477a9b4a58539 /src | |
parent | e1976796bf99ddc6f9f8b946b5cdea26e9e5245a (diff) |
Fix possible use of invalid iterator on module unload
When a module quits a user or destroys a channel in OnCleanup() the object is no longer in the container being iterated by the time OnCleanup() returns
Diffstat (limited to 'src')
-rw-r--r-- | src/modules.cpp | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/src/modules.cpp b/src/modules.cpp index d25e145e3..b2d2f23c6 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -352,18 +352,23 @@ void ModuleManager::DoSafeUnload(Module* mod) std::vector<reference<ExtensionItem> > items; ServerInstance->Extensions.BeginUnregister(modfind->second, items); /* Give the module a chance to tidy out all its metadata */ - for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++) + for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); ) { - mod->OnCleanup(TYPE_CHANNEL,c->second); - c->second->doUnhookExtensions(items); - const UserMembList* users = c->second->GetUsers(); + Channel* chan = c->second; + ++c; + mod->OnCleanup(TYPE_CHANNEL, chan); + chan->doUnhookExtensions(items); + const UserMembList* users = chan->GetUsers(); for(UserMembCIter mi = users->begin(); mi != users->end(); mi++) mi->second->doUnhookExtensions(items); } - for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++) + for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); ) { - mod->OnCleanup(TYPE_USER,u->second); - u->second->doUnhookExtensions(items); + User* user = u->second; + // The module may quit the user (e.g. SSL mod unloading) and that will remove it from the container + ++u; + mod->OnCleanup(TYPE_USER, user); + user->doUnhookExtensions(items); } for(char m='A'; m <= 'z'; m++) { |