diff --git a/Zip/include/Poco/Zip/ZipArchive.h b/Zip/include/Poco/Zip/ZipArchive.h index aa5a8498c..150f003e9 100644 --- a/Zip/include/Poco/Zip/ZipArchive.h +++ b/Zip/include/Poco/Zip/ZipArchive.h @@ -24,7 +24,6 @@ #include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipFileInfo.h" #include "Poco/Zip/ZipArchiveInfo.h" - #include #include diff --git a/Zip/src/AutoDetectStream.cpp b/Zip/src/AutoDetectStream.cpp index 1229e3294..3664df9a1 100644 --- a/Zip/src/AutoDetectStream.cpp +++ b/Zip/src/AutoDetectStream.cpp @@ -69,6 +69,7 @@ int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) { _pIstr->seekg(_start, std::ios_base::beg); _reposition = false; + if (!_pIstr->good()) return -1; } if (!_prefix.empty()) @@ -145,11 +146,9 @@ int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) { if (c-1 == byte3) { - // a match, pushback - _pIstr->putback(c); - _pIstr->putback(byte3); - _pIstr->putback(ZipLocalFileHeader::HEADER[1]); - _pIstr->putback(ZipLocalFileHeader::HEADER[0]); + // a match, seek back + _pIstr->seekg(-4, std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); _eofDetected = true; return tempPos; } diff --git a/Zip/src/Compress.cpp b/Zip/src/Compress.cpp index b335a3074..b74333d1a 100644 --- a/Zip/src/Compress.cpp +++ b/Zip/src/Compress.cpp @@ -78,7 +78,7 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, _offset = hdr.getEndPos(); _offset += extraDataSize; _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); nfo.setZip64Data(); @@ -89,12 +89,13 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName) { + if (!in.good()) + throw ZipException("Invalid input stream"); + std::string fn = ZipUtil::validZipEntryFileName(fileName); //bypass the header of the input stream and point to the first byte of the data payload in.seekg(h.getDataStartPos(), std::ios_base::beg); - - if (!in.good()) - throw ZipException("Invalid input stream"); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); std::streamoff localHeaderOffset = _offset; ZipLocalFileHeader hdr(h); @@ -161,7 +162,7 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P } _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); nfo.setZip64Data(); @@ -229,7 +230,7 @@ void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& l if (hdr.searchCRCAndSizesAfterData()) _offset += extraDataSize; _files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr)); - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); nfo.setZip64Data(); @@ -314,7 +315,7 @@ ZipArchive Compress::close() centralDirSize64 += entrySize; _offset += entrySize; } - poco_assert (_out); + if (!_out) throw Poco::IOException("Bad output stream"); Poco::UInt64 numEntries64 = _infos.size(); needZip64 = needZip64 || _offset >= ZipCommon::ZIP64_MAGIC; diff --git a/Zip/src/Decompress.cpp b/Zip/src/Decompress.cpp index 2f94fa949..e01f47e9d 100644 --- a/Zip/src/Decompress.cpp +++ b/Zip/src/Decompress.cpp @@ -39,7 +39,7 @@ Decompress::Decompress(std::istream& in, const Poco::Path& outputDir, bool flatt { _outDir.makeAbsolute(); _outDir.makeDirectory(); - poco_assert (_in.good()); + if (!_in.good()) throw Poco::IOException("Bad input stream"); Poco::File tmp(_outDir); if (!tmp.exists()) { diff --git a/Zip/src/PartialStream.cpp b/Zip/src/PartialStream.cpp index 85587278e..d6d9e302b 100644 --- a/Zip/src/PartialStream.cpp +++ b/Zip/src/PartialStream.cpp @@ -69,7 +69,7 @@ int PartialStreamBuf::readFromDevice(char* buffer, std::streamsize length) _pIstr->clear(); _pIstr->seekg(_start, std::ios_base::beg); if (_pIstr->fail()) - throw Poco::IOException("Failed to reposition in stream"); + throw Poco::IOException("Failed to seek on input stream"); } if (!_prefix.empty()) { diff --git a/Zip/src/SkipCallback.cpp b/Zip/src/SkipCallback.cpp index 20d0ca491..febbd0af6 100644 --- a/Zip/src/SkipCallback.cpp +++ b/Zip/src/SkipCallback.cpp @@ -17,6 +17,7 @@ #include "Poco/Zip/SkipCallback.h" #include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipUtil.h" +#include "Poco/Exception.h" namespace Poco { @@ -39,6 +40,7 @@ bool SkipCallback::handleZipEntry(std::istream& zipStream, const ZipLocalFileHea zipStream.seekg(hdr.getCompressedSize(), std::ios_base::cur); else ZipUtil::sync(zipStream); + if (!zipStream.good()) throw Poco::IOException("Failed to seek on input stream"); return true; } diff --git a/Zip/src/ZipArchiveInfo.cpp b/Zip/src/ZipArchiveInfo.cpp index 9299eb4cb..6985efab3 100644 --- a/Zip/src/ZipArchiveInfo.cpp +++ b/Zip/src/ZipArchiveInfo.cpp @@ -59,12 +59,16 @@ void ZipArchiveInfo::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read archive info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad archive info header"); } else { std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); Poco::UInt16 len = getZipCommentSize(); @@ -136,12 +140,16 @@ void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read archive info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad archive info header"); } else { std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + std::memset(_rawInfo + ZipCommon::HEADER_SIZE, 0, FULL_HEADER_SIZE - ZipCommon::HEADER_SIZE); // read the rest of the header @@ -164,7 +172,11 @@ void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead) ZipUtil::set64BitValue(FULL_HEADER_SIZE + len - offset, _rawInfo, RECORDSIZE_POS); } inp.read(_locInfo, FULL_LOCATOR_SIZE); - poco_assert (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) == 0); + if (inp.gcount() != FULL_LOCATOR_SIZE) + throw Poco::IOException("Failed to read locator"); + if (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad locator header"); + } diff --git a/Zip/src/ZipDataInfo.cpp b/Zip/src/ZipDataInfo.cpp index c2b6bf645..e03b82074 100644 --- a/Zip/src/ZipDataInfo.cpp +++ b/Zip/src/ZipDataInfo.cpp @@ -15,6 +15,7 @@ #include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Exception.h" #include #include @@ -47,10 +48,11 @@ ZipDataInfo::ZipDataInfo(std::istream& in, bool assumeHeaderRead): else { in.read(_rawInfo, ZipCommon::HEADER_SIZE); - if ((!in) || (in.gcount() != ZipCommon::HEADER_SIZE)) - return; + if (in.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read data info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad data info header"); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); // now copy the rest of the header in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); _valid = (!in.eof() && in.good()); @@ -87,10 +89,12 @@ ZipDataInfo64::ZipDataInfo64(std::istream& in, bool assumeHeaderRead): else { in.read(_rawInfo, ZipCommon::HEADER_SIZE); - if ((!in) || (in.gcount() != ZipCommon::HEADER_SIZE)) - return; + if (in.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read data info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad data info header"); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // now copy the rest of the header in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); _valid = (!in.eof() && in.good()); diff --git a/Zip/src/ZipFileInfo.cpp b/Zip/src/ZipFileInfo.cpp index e29cd73c8..e23d0870e 100644 --- a/Zip/src/ZipFileInfo.cpp +++ b/Zip/src/ZipFileInfo.cpp @@ -87,12 +87,16 @@ void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read file info header"); + if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad file info header"); } else { std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); _crc32 = getCRCFromHeader(); diff --git a/Zip/src/ZipLocalFileHeader.cpp b/Zip/src/ZipLocalFileHeader.cpp index 7b7f63a1c..aab16fdf1 100644 --- a/Zip/src/ZipLocalFileHeader.cpp +++ b/Zip/src/ZipLocalFileHeader.cpp @@ -118,13 +118,17 @@ void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) if (!assumeHeaderRead) { inp.read(_rawHeader, ZipCommon::HEADER_SIZE); + if (inp.gcount() != ZipCommon::HEADER_SIZE) + throw Poco::IOException("Failed to read local file header"); + if (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) != 0) + throw Poco::DataFormatException("Bad local file header"); } else { std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); } - poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0); - // read the rest of the header + + // read the rest of the header inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); poco_assert (_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED); poco_assert (getMajorVersionNumber() <= 4); // Allow for Zip64 version 4.5 diff --git a/Zip/src/ZipManipulator.cpp b/Zip/src/ZipManipulator.cpp index 5fc00e9ae..73e8e7e1c 100644 --- a/Zip/src/ZipManipulator.cpp +++ b/Zip/src/ZipManipulator.cpp @@ -111,7 +111,7 @@ const ZipLocalFileHeader& ZipManipulator::getForChange(const std::string& zipPat { ZipArchive::FileHeaders::const_iterator it = _in->findHeader(zipPath); if (it == _in->headerEnd()) - throw ZipManipulationException("entry not found: " + zipPath); + throw ZipManipulationException("Entry not found: " + zipPath); if (_changes.find(zipPath) != _changes.end()) throw ZipManipulationException("A change request exists already for entry " + zipPath); diff --git a/Zip/src/ZipStream.cpp b/Zip/src/ZipStream.cpp index fdda20eb2..26514feb5 100644 --- a/Zip/src/ZipStream.cpp +++ b/Zip/src/ZipStream.cpp @@ -177,8 +177,8 @@ int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length) Poco::Int32 size = static_cast(nfo.getFullHeaderSize()); _expectedCrc32 = nfo.getCRC32(); const char* rawHeader = nfo.getRawHeader(); - for (Poco::Int32 i = size-1; i >= 0; --i) - _pIstr->putback(rawHeader[i]); + _pIstr->seekg(-size, std::ios::cur); + if (!_pIstr->good()) throw Poco::IOException("Failed to seek on input stream"); if (!crcValid()) throw ZipException("CRC failure"); } @@ -215,7 +215,8 @@ void ZipStreamBuf::close(Poco::UInt64& extraDataSize) _ptrOHelper->close(); } _ptrOBuf = 0; - poco_assert (*_pOstr); + if (!*_pOstr) throw Poco::IOException("Bad output stream"); + // write an extra datablock if required // or fix the crc entries poco_check_ptr(_pHeader); @@ -248,13 +249,14 @@ void ZipStreamBuf::close(Poco::UInt64& extraDataSize) else { _pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); - poco_assert (*_pOstr); + if (!*_pOstr) throw Poco::IOException("Bad output stream"); + if (_pHeader->hasExtraField()) // Update sizes in header extension. _pHeader->setZip64Data(); std::string header = _pHeader->createHeader(); _pOstr->write(header.c_str(), static_cast(header.size())); _pOstr->seekp(0, std::ios_base::end); - poco_assert (*_pOstr); + if (!*_pOstr) throw Poco::IOException("Bad output stream"); } _pHeader = 0; } diff --git a/Zip/src/ZipUtil.cpp b/Zip/src/ZipUtil.cpp index 069074651..7bdb76dfe 100644 --- a/Zip/src/ZipUtil.cpp +++ b/Zip/src/ZipUtil.cpp @@ -117,31 +117,23 @@ void ZipUtil::sync(std::istream& in) { if (std::memcmp(ZipLocalFileHeader::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) { - in.putback(ZipLocalFileHeader::HEADER[3]); - in.putback(ZipLocalFileHeader::HEADER[2]); - in.putback(ZipLocalFileHeader::HEADER[1]); - in.putback(ZipLocalFileHeader::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } else if (std::memcmp(ZipArchiveInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) { - in.putback(ZipArchiveInfo::HEADER[3]); - in.putback(ZipArchiveInfo::HEADER[2]); - in.putback(ZipArchiveInfo::HEADER[1]); - in.putback(ZipArchiveInfo::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } else if (std::memcmp(ZipFileInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) { - in.putback(ZipFileInfo::HEADER[3]); - in.putback(ZipFileInfo::HEADER[2]); - in.putback(ZipFileInfo::HEADER[1]); - in.putback(ZipFileInfo::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } else { - in.putback(ZipDataInfo::HEADER[3]); - in.putback(ZipDataInfo::HEADER[2]); - in.putback(ZipDataInfo::HEADER[1]); - in.putback(ZipDataInfo::HEADER[0]); + in.seekg(-4, std::ios::cur); + if (!in.good()) throw Poco::IOException("Failed to seek on input stream"); } return; } @@ -149,6 +141,7 @@ void ZipUtil::sync(std::istream& in) { // we have read 2 bytes, should only be one: putback the last char in.putback(temp[tempPos - 1]); + if (!in.good()) throw Poco::IOException("Failed to putback on input stream"); --tempPos; } }