Zipper: added an overflow check to make sure to produce a valid zip (next step is to implement zip64)
This commit is contained in:
@@ -176,7 +176,21 @@ namespace Zip
|
|||||||
throw ZipperException {"Cannot get file size for '" + filePath.string() + "': " + ec.message()};
|
throw ZipperException {"Cannot get file size for '" + filePath.string() + "': " + ec.message()};
|
||||||
|
|
||||||
_files[filename] = std::move(fileContext);
|
_files[filename] = std::move(fileContext);
|
||||||
|
|
||||||
|
_totalZipSize += LocalFileHeader::getHeaderSize();
|
||||||
|
_totalZipSize += filename.size();
|
||||||
|
if (fileContext.fileSize > 0)
|
||||||
|
{
|
||||||
|
_totalZipSize += fileContext.fileSize;
|
||||||
|
_totalZipSize += DataDescriptor::getHeaderSize();
|
||||||
|
_totalZipSize += CentralDirectoryHeader::getHeaderSize();
|
||||||
|
_totalZipSize += filename.size();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_totalZipSize += EndOfCentralDirectoryRecord::getHeaderSize();
|
||||||
|
if (_totalZipSize > UINT32_MAX)
|
||||||
|
throw ZipperException {"Cannot create a zip file which is larger than " + std::to_string(UINT32_MAX) + " bytes!"};
|
||||||
|
|
||||||
_currentFile = std::begin(_files);
|
_currentFile = std::begin(_files);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,12 +39,16 @@ namespace Zip
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
using SizeZype = std::uint64_t;
|
||||||
|
|
||||||
Zipper(const std::map<std::string, std::filesystem::path>& files);
|
Zipper(const std::map<std::string, std::filesystem::path>& files);
|
||||||
|
|
||||||
static constexpr std::size_t minOutputBufferSize = 64;
|
static constexpr std::size_t minOutputBufferSize = 64;
|
||||||
std::size_t writeSome(std::byte* buffer, std::size_t bufferSize);
|
std::size_t writeSome(std::byte* buffer, std::size_t bufferSize);
|
||||||
bool isComplete() const;
|
bool isComplete() const;
|
||||||
|
|
||||||
|
SizeZype getTotalZipFile() const { return _totalZipSize; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setComplete();
|
void setComplete();
|
||||||
|
|
||||||
@@ -79,6 +83,7 @@ namespace Zip
|
|||||||
Complete,
|
Complete,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SizeZype _totalZipSize {};
|
||||||
WriteState _writeState {WriteState::LocalFileHeader};
|
WriteState _writeState {WriteState::LocalFileHeader};
|
||||||
FileContainer::iterator _currentFile;
|
FileContainer::iterator _currentFile;
|
||||||
std::size_t _currentOffset {};
|
std::size_t _currentOffset {};
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ int main(int argc, char* argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
Zipper zipper {files};
|
Zipper zipper {files};
|
||||||
|
|
||||||
while (!zipper.isComplete())
|
while (!zipper.isComplete())
|
||||||
@@ -68,5 +70,13 @@ int main(int argc, char* argv[])
|
|||||||
ofs.write(reinterpret_cast<const char*>(buffer.data()), nbWrittenBytes);
|
ofs.write(reinterpret_cast<const char*>(buffer.data()), nbWrittenBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "Total zip size = " << zipper.getTotalZipFile() << std::endl;
|
||||||
|
}
|
||||||
|
catch (const ZipperException& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Caught Zipper exception: " << e.what() << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user