diff --git a/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp b/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp index cb30f6cb..bd7edfd6 100644 --- a/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp +++ b/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp @@ -219,14 +219,20 @@ void plResManager::IShutdown() // Shut down the registry (finally!) ILockPages(); - PageSet::const_iterator it; - for (it = fAllPages.begin(); it != fAllPages.end(); it++) + // Unload all keys before actually deleting the pages. + // When a key's refcount drops to zero, IKeyUnreffed looks up the key's page. + // If the page is already deleted at that point, this causes a use after free and potential crash. + for (PageSet::const_iterator it = fAllPages.begin(); it != fAllPages.end(); it++) { + (*it)->UnloadKeys(); + } + fLoadedPages.clear(); + fLastFoundPage = nil; + for (PageSet::const_iterator it = fAllPages.begin(); it != fAllPages.end(); it++) { delete *it; + } fAllPages.clear(); - fLoadedPages.clear(); IUnlockPages(); - fLastFoundPage = nil; // Now, kill off the Dispatcher hsRefCnt_SafeUnRef(fDispatch);