From b9d1af9f46cbd0c9ef97156b3bd71bafbdc1ee0e Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Mon, 20 Sep 2021 15:44:07 -0500 Subject: [PATCH] Fixed calculation of each archive file data offset. (#4204) * Fixed calculation of each archive file data offset. The location of a file entry in a Zip file is calculated after the local file header + the length of the filename + the length of the extra field length per the ZIP file spec. https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed bIndependentBlocks variable Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AzFramework/Archive/ZipDirCache.cpp | 2 +- .../Archive/ZipDirCacheFactory.cpp | 5 ++-- .../AzFramework/Archive/ZipDirStructures.cpp | 28 ++++++++----------- .../AzFramework/Archive/ZipDirStructures.h | 2 +- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp index 328541c4d0..d17dbd0837 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp @@ -774,7 +774,7 @@ namespace AZ::IO::ZipDir return ZD_ERROR_INVALID_CALL; } - if (pFileEntry->nFileDataOffset != pFileEntry->INVALID_DATA_OFFSET) + if (pFileEntry->nFileDataOffset != FileEntryBase::INVALID_DATA_OFFSET) { return ZD_ERROR_SUCCESS; // the data offset has been successfully read.. } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp index 6adab594ed..5c5e93d441 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp @@ -553,7 +553,7 @@ namespace AZ::IO::ZipDir ////////////////////////////////////////////////////////////////////////// // give the CDR File Header entry, reads the local file header to validate - // and determine where the actual file lies + // and determine where the actual file resides void CacheFactory::AddFileEntry(char* strFilePath, const ZipFile::CDRFileHeader* pFileHeader, const SExtraZipFileData& extra) { if (pFileHeader->lLocalHeaderOffset > m_CDREnd.lCDROffset) @@ -600,8 +600,7 @@ namespace AZ::IO::ZipDir if (m_encryptedHeaders != ZipFile::HEADERS_NOT_ENCRYPTED) { // use CDR instead of local header - // The pak encryption tool asserts that there is no extra data at the end of the local file header, so don't add any extra data from the CDR header. - fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + pFileHeader->nFileNameLength; + fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + pFileHeader->nFileNameLength + pFileHeader->nExtraFieldLength; } else { diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index f9aa249339..cea517decd 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -187,8 +187,7 @@ namespace AZ::IO::ZipDir::ZipDirStructuresInternal // If src/dst overlap (in place decompress), then inflate in chunks, copying src locally to ensure // pointers don't foul each other. - bool bIndependantBlocks = ((pInput + nInputLen) <= pOutput) || (pInput >= (pOutput + nOutputLen)); - if (bIndependantBlocks) + if ((pInput + nInputLen) <= pOutput || pInput >= (pOutput + nOutputLen)) { pZStream->next_in = (Bytef*)pInput; pZStream->avail_in = aznumeric_cast(nInputLen); @@ -260,8 +259,7 @@ namespace AZ::IO::ZipDir::ZipDirStructuresInternal // If src/dst overlap (in place decompress), then inflate in chunks, copying src locally to ensure // pointers don't foul each other. - bool bIndependantBlocks = ((pIn + nIn) <= stream.next_out) || (pIn >= (stream.next_out + stream.avail_out)); - if (bIndependantBlocks) + if ((pIn + nIn) <= stream.next_out || pIn >= (stream.next_out + stream.avail_out)) { stream.next_in = pIn; stream.avail_in = nIn; @@ -498,18 +496,18 @@ namespace AZ::IO::ZipDir ////////////////////////////////////////////////////////////////////////// FileEntryBase::FileEntryBase(const ZipFile::CDRFileHeader& header, const SExtraZipFileData& extra) { - this->desc = header.desc; - this->nFileHeaderOffset = header.lLocalHeaderOffset; - //this->nFileDataOffset = INVALID_DATA_OFFSET; // we don't know yet - this->nMethod = header.nMethod; - this->nNameOffset = 0; // we don't know yet - this->nLastModTime = header.nLastModTime; - this->nLastModDate = header.nLastModDate; - this->nNTFS_LastModifyTime = extra.nLastModifyTime; + desc = header.desc; + nFileHeaderOffset = header.lLocalHeaderOffset; + + nMethod = header.nMethod; + nNameOffset = 0; // we don't know yet + nLastModTime = header.nLastModTime; + nLastModDate = header.nLastModDate; + nNTFS_LastModifyTime = extra.nLastModifyTime; // make an estimation (at least this offset should be there), but we don't actually know yet - this->nFileDataOffset = header.lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + header.nFileNameLength; - this->nEOFOffset = header.lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + header.nFileNameLength + header.desc.lSizeCompressed; + nFileDataOffset = header.lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + header.nFileNameLength + header.nExtraFieldLength; + nEOFOffset = nFileDataOffset + header.desc.lSizeCompressed; } // Uncompresses raw (without wrapping) data that is compressed with method 8 (deflated) in the Zip file @@ -817,8 +815,6 @@ namespace AZ::IO::ZipDir header.nFileNameLength = aznumeric_cast(nFileNameLength); header.nExtraFieldLength = 0; - pFileEntry->nFileDataOffset = pFileEntry->nFileHeaderOffset + sizeof(header) + header.nFileNameLength; - pFileEntry->nEOFOffset = pFileEntry->nFileDataOffset + pFileEntry->desc.lSizeCompressed; if (!AZ::IO::FileIOBase::GetDirectInstance()->Write(fileHandle, &header, sizeof(header))) { return ZD_ERROR_IO_FAILED; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h index 7e1d54b405..9295a7dd95 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h @@ -169,7 +169,7 @@ namespace AZ::IO::ZipDir inline static constexpr uint32_t INVALID_DATA_OFFSET = 0xFFFFFFFF; ZipFile::DataDescriptor desc{}; - uint32_t nFileDataOffset{}; // offset of the packed info inside the file; NOTE: this can be INVALID_DATA_OFFSET, if not calculated yet! + uint32_t nFileDataOffset{ INVALID_DATA_OFFSET }; // offset of the packed info inside the file; NOTE: this can be INVALID_DATA_OFFSET, if not calculated yet! uint32_t nFileHeaderOffset{ INVALID_DATA_OFFSET }; // offset of the local file header uint32_t nNameOffset{}; // offset of the file name in the name pool for the directory