From 74b9eb2f73ecc84bf075c892b261999efc86eb30 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sat, 5 Mar 2022 18:47:12 -0330 Subject: [PATCH] Fix lockup on ZIP files containing errors (fixes #871). --- src/common/FSNodeZIP.cxx | 23 +++++++++++++++++------ src/common/ZipHandler.cxx | 17 +++++++++++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index b8232c657..aea856799 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -39,7 +39,7 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) if (_zipFile[0] == '~') { #if defined(BSPF_UNIX) || defined(BSPF_MACOS) - string home = BSPF::getenv("HOME"); + const string& home = BSPF::getenv("HOME"); if (home != EmptyString) _zipFile.replace(0, 1, home); #elif defined(BSPF_WINDOWS) @@ -71,6 +71,9 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) _virtualPath = p.substr(pos+5); _isFile = Bankswitch::isValidRomName(_virtualPath); _isDirectory = !_isFile; + +// cerr << _virtualPath << ", isfile: " << _isFile << endl; + } else if(_numFiles == 1) { @@ -97,7 +100,8 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) // has direct access to the actual filesystem (aka, a 'System' node) // Behind the scenes, this node is actually a platform-specific object // for whatever system we are running on - _realNode = FilesystemNodeFactory::create(_zipFile, FilesystemNodeFactory::Type::SYSTEM); + _realNode = FilesystemNodeFactory::create(_zipFile, + FilesystemNodeFactory::Type::SYSTEM); setFlags(_zipFile, _virtualPath, _realNode); } @@ -144,10 +148,17 @@ bool FilesystemNodeZIP::exists() const if(_realNode && _realNode->exists()) { // We need to inspect the actual path, not just the ZIP file itself - myZipHandler->open(_zipFile); - while(myZipHandler->hasNext()) - if(BSPF::startsWithIgnoreCase(myZipHandler->next(), _virtualPath)) - return true; + try + { + myZipHandler->open(_zipFile); + while(myZipHandler->hasNext()) + if(BSPF::startsWithIgnoreCase(myZipHandler->next(), _virtualPath)) + return true; + } + catch(const runtime_error&) + { + // TODO: Actually present the error passed in back to the user + } } return false; diff --git a/src/common/ZipHandler.cxx b/src/common/ZipHandler.cxx index 53efe3edc..01118f988 100644 --- a/src/common/ZipHandler.cxx +++ b/src/common/ZipHandler.cxx @@ -63,9 +63,16 @@ void ZipHandler::open(const string& filename) myZip = std::move(ptr); // Count ROM files (we do it here so it will be cached) - while(hasNext()) - if(Bankswitch::isValidRomName(next())) - myZip->myRomfiles++; + try + { + while(hasNext()) + if(Bankswitch::isValidRomName(next())) + myZip->myRomfiles++; + } + catch(...) + { + myZip->myRomfiles = 0; + } } reset(); // Reset iterator to beginning for subsequent use @@ -91,7 +98,9 @@ const string& ZipHandler::next() if(hasNext()) { const ZipHeader* header = myZip->nextFile(); - if(!header || header->uncompressedLength == 0) + if(!header) + throw runtime_error(errorMessage(ZipError::FILE_CORRUPT)); + else if(header->uncompressedLength == 0) return next(); else return header->filename;