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() {
// Initialize all savegames' descriptions to empty strings
memset(currentSaveName, 0, sizeof(currentSaveName));
// Resize object table to its correct size and reset all its elements
objectTable.resize(NUM_MAX_OBJECT);
resetObjectTable();

View file

@ -607,35 +607,37 @@ SaveStateList CineMetaEngine::listSaves(const char *target) const {
pattern += ".?";
Common::StringList filenames = saveFileMan->listSavefiles(pattern);
sort(filenames.begin(), filenames.end());
Common::StringList::const_iterator file = filenames.begin();
Common::StringList::const_iterator file;
Common::String filename = target;
filename += ".dir";
Common::InSaveFile *in = saveFileMan->openForLoading(filename);
if (in) {
int8 ch;
char saveDesc[20];
do {
typedef char CommandeType[20];
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));
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
int slotNum = atoi(file->c_str() + file->size() - 1);
uint pos = 0;
do {
ch = in->readByte();
if (pos < (sizeof(saveDesc) - 1)) {
if (ch < 32 || in->eos()) {
saveDesc[pos++] = '\0';
}
else if (ch >= 32) {
saveDesc[pos++] = ch;
}
}
} while (ch >= 32 && !in->eos());
if (saveDesc[0] != 0) {
// Copy the savegame description making sure it ends with a trailing zero
strncpy(saveDesc, saveNames[slotNum], 20);
saveDesc[sizeof(CommandeType) - 1] = 0;
saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
file++;
}
} while (!in->eos());
}
delete in;
@ -650,6 +652,11 @@ void CineMetaEngine::removeSaveState(const char *target, int slot) const {
typedef char CommandeType[20];
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;
char tmp[80];
@ -707,8 +714,9 @@ Common::Error CineEngine::saveGameState(int slot, const char *desc) {
// Load savegame descriptions from index file
loadSaveDirectory();
// Set description for selected slot
// Set description for selected slot making sure it ends with a trailing zero
strncpy(currentSaveName[slot], desc, 20);
currentSaveName[slot][sizeof(CommandeType) - 1] = 0;
// Update savegame descriptions
char indexFile[80];

View file

@ -468,9 +468,18 @@ bool CineEngine::loadSaveDirectory(void) {
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);
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;
}