Fix for #2824798 (FW: crash when clicking "load" in the GUI):

- Fixed CineMetaEngine::listSaves(const char *target) which was broken.
- Also added explicit initialization of savegame descriptions to
  empty strings for safety reasons (e.g. arrays on stack aren't
  initialized to zero).
- Added explicit trailing zero setting to savegame descriptions
  (Previously using GMM you could write a description of length >= 20
  that had no trailing zero when written to description file (e.g. fw.dir)).

svn-id: r43027
This commit is contained in:
Kari Salminen 2009-08-03 17:52:07 +00:00
parent 9931fb6a44
commit c2dc86df08
3 changed files with 42 additions and 22 deletions

View file

@ -114,6 +114,9 @@ int CineEngine::modifyGameSpeed(int speedChange) {
} }
void CineEngine::initialize() { void CineEngine::initialize() {
// Initialize all savegames' descriptions to empty strings
memset(currentSaveName, 0, sizeof(currentSaveName));
// Resize object table to its correct size and reset all its elements // Resize object table to its correct size and reset all its elements
objectTable.resize(NUM_MAX_OBJECT); objectTable.resize(NUM_MAX_OBJECT);
resetObjectTable(); resetObjectTable();

View file

@ -607,35 +607,37 @@ SaveStateList CineMetaEngine::listSaves(const char *target) const {
pattern += ".?"; pattern += ".?";
Common::StringList filenames = saveFileMan->listSavefiles(pattern); Common::StringList filenames = saveFileMan->listSavefiles(pattern);
sort(filenames.begin(), filenames.end()); sort(filenames.begin(), filenames.end());
Common::StringList::const_iterator file = filenames.begin(); Common::StringList::const_iterator file;
Common::String filename = target; Common::String filename = target;
filename += ".dir"; filename += ".dir";
Common::InSaveFile *in = saveFileMan->openForLoading(filename); Common::InSaveFile *in = saveFileMan->openForLoading(filename);
if (in) { if (in) {
int8 ch; typedef char CommandeType[20];
char saveDesc[20]; CommandeType saveNames[10];
do {
// Initialize all savegames' descriptions to empty strings
// so that if the savegames' descriptions can only be partially read from file
// then the missing ones are correctly set to empty strings.
memset(saveNames, 0, sizeof(saveNames));
in->read(saveNames, 10 * 20);
CommandeType saveDesc;
for (file = filenames.begin(); file != filenames.end(); ++file) {
// Jump over savegame files that don't end with a digit (e.g. "fw.3" is ok, "fw.a" is not).
if (!isdigit(file->lastChar()))
continue;
// Obtain the last digit of the filename, since they correspond to the save slot // Obtain the last digit of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 1); int slotNum = atoi(file->c_str() + file->size() - 1);
uint pos = 0; // Copy the savegame description making sure it ends with a trailing zero
do { strncpy(saveDesc, saveNames[slotNum], 20);
ch = in->readByte(); saveDesc[sizeof(CommandeType) - 1] = 0;
if (pos < (sizeof(saveDesc) - 1)) {
if (ch < 32 || in->eos()) { saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
saveDesc[pos++] = '\0'; }
}
else if (ch >= 32) {
saveDesc[pos++] = ch;
}
}
} while (ch >= 32 && !in->eos());
if (saveDesc[0] != 0) {
saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
file++;
}
} while (!in->eos());
} }
delete in; delete in;
@ -650,6 +652,11 @@ void CineMetaEngine::removeSaveState(const char *target, int slot) const {
typedef char CommandeType[20]; typedef char CommandeType[20];
CommandeType saveNames[10]; CommandeType saveNames[10];
// Initialize all savegames' descriptions to empty strings
// so that if the savegames' descriptions can only be partially read from file
// then the missing ones are correctly set to empty strings.
memset(saveNames, 0, sizeof(saveNames));
Common::InSaveFile *in; Common::InSaveFile *in;
char tmp[80]; char tmp[80];
@ -707,8 +714,9 @@ Common::Error CineEngine::saveGameState(int slot, const char *desc) {
// Load savegame descriptions from index file // Load savegame descriptions from index file
loadSaveDirectory(); loadSaveDirectory();
// Set description for selected slot // Set description for selected slot making sure it ends with a trailing zero
strncpy(currentSaveName[slot], desc, 20); strncpy(currentSaveName[slot], desc, 20);
currentSaveName[slot][sizeof(CommandeType) - 1] = 0;
// Update savegame descriptions // Update savegame descriptions
char indexFile[80]; char indexFile[80];

View file

@ -468,9 +468,18 @@ bool CineEngine::loadSaveDirectory(void) {
return false; return false;
} }
// Initialize all savegames' descriptions to empty strings
// so that if the savegames' descriptions can only be partially read from file
// then the missing ones are correctly set to empty strings.
memset(currentSaveName, 0, sizeof(currentSaveName));
fHandle->read(currentSaveName, 10 * 20); fHandle->read(currentSaveName, 10 * 20);
delete fHandle; delete fHandle;
// Make sure all savegames' descriptions end with a trailing zero.
for (int i = 0; i < ARRAYSIZE(currentSaveName); i++)
currentSaveName[i][sizeof(CommandeType) - 1] = 0;
return true; return true;
} }