From 13f74027e8e561662bad29bac9f9950782a2ebea Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Nov 2017 21:05:40 -0500 Subject: TSAGE: Fix loading savegames with unreferenced dynamic objects --- engines/tsage/saveload.cpp | 14 ++++++++++++-- engines/tsage/saveload.h | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'engines/tsage') diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp index 3cb8e52692..03f615db21 100644 --- a/engines/tsage/saveload.cpp +++ b/engines/tsage/saveload.cpp @@ -211,12 +211,14 @@ Common::Error Saver::restore(int slot) { // Note: I don't store pointers to instantiated objects here, because it's not necessary - the mere act // of instantiating a saved object registers it with the saver, and will then be resolved to whatever // object originally had a pointer to it as part of the post-processing step + DynObjects dynObjects; Common::String className; serializer.syncString(className); while (className != "END") { SavedObject *savedObject; if (!_factoryPtr || ((savedObject = _factoryPtr(className)) == NULL)) error("Unknown class name '%s' encountered trying to restore savegame", className.c_str()); + dynObjects.push_back(savedObject); // Populate the contents of the object savedObject->synchronize(serializer); @@ -226,7 +228,12 @@ Common::Error Saver::restore(int slot) { } // Post-process any unresolved pointers to get the correct pointer - resolveLoadPointers(); + resolveLoadPointers(dynObjects); + + // Post-process safety check: if any dynamically created objects didn't get any + // references, then delete them, since they'd never be freed otherwise + for (DynObjects::iterator i = dynObjects.begin(); i != dynObjects.end(); ++i) + delete *i; delete saveFile; @@ -392,7 +399,7 @@ void Saver::listObjects() { /** * Returns the pointer associated with the specified object index */ -void Saver::resolveLoadPointers() { +void Saver::resolveLoadPointers(DynObjects &dynObjects) { if (_unresolvedPtrs.size() == 0) // Nothing to resolve return; @@ -410,6 +417,9 @@ void Saver::resolveLoadPointers() { SavedObject **objPP = r._savedObject; *objPP = pObj; iPtr = _unresolvedPtrs.erase(iPtr); + + // If it's a dynamic object, remove it from the dynamic objects list + dynObjects.remove(pObj); } else { ++iPtr; } diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h index be5ff51ffb..04a1e02b28 100644 --- a/engines/tsage/saveload.h +++ b/engines/tsage/saveload.h @@ -201,6 +201,7 @@ public: typedef SavedObject *(*SavedObjectFactory)(const Common::String &className); class Saver { + typedef Common::List DynObjects; private: Common::List _objList; FunctionList _saveNotifiers; @@ -213,7 +214,7 @@ private: bool _macroSaveFlag; bool _macroRestoreFlag; - void resolveLoadPointers(); + void resolveLoadPointers(DynObjects &dynObjects); public: Saver(); ~Saver(); -- cgit v1.2.3