COMMON: Add proper error handling to the ZipArchive class

- Add check in listMembers and skip files that can't be enumerated.
 - Add checks for all function calls in createReadStreamForMember (and no longer return a stream from an uninitialized buffer when the file cannot be read).
This commit is contained in:
Littleboy 2011-04-24 23:53:24 -04:00
parent ea9774f689
commit 55650f364c

View file

@ -1470,11 +1470,13 @@ int ZipArchive::listMembers(Common::ArchiveMemberList &list) {
while (err == UNZ_OK) {
char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
unzGetCurrentFileInfo(_zipFile, NULL,
szCurrentFileName, sizeof(szCurrentFileName)-1,
NULL, 0, NULL, 0);
list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(szCurrentFileName, this)));
matches++;
if (unzGetCurrentFileInfo(_zipFile, NULL,
szCurrentFileName, sizeof(szCurrentFileName)-1,
NULL, 0, NULL, 0) == UNZ_OK) {
list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(szCurrentFileName, this)));
matches++;
}
err = unzGoToNextFile(_zipFile);
}
@ -1493,18 +1495,31 @@ Common::SeekableReadStream *ZipArchive::createReadStreamForMember(const Common::
return 0;
unz_file_info fileInfo;
unzOpenCurrentFile(_zipFile);
unzGetCurrentFileInfo(_zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
if (unzOpenCurrentFile(_zipFile) != UNZ_OK)
return 0;
if (unzGetCurrentFileInfo(_zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK)
return 0;
byte *buffer = (byte *)malloc(fileInfo.uncompressed_size);
assert(buffer);
unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size);
unzCloseCurrentFile(_zipFile);
if (unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size) != (int)fileInfo.uncompressed_size) {
free(buffer);
return 0;
}
if (unzCloseCurrentFile(_zipFile) != UNZ_OK) {
free(buffer);
return 0;
}
return new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size, DisposeAfterUse::YES);
// FIXME: instead of reading all into a memory stream, we could
// instead create a new ZipStream class. But then we have to be
// careful to handle the case where the client code opens multiple
// files in the archive and tries to use them indepenendtly.
// files in the archive and tries to use them independently.
}
Archive *makeZipArchive(const String &name) {